From ecc722ad418a926af4e383f8977444717786fe20 Mon Sep 17 00:00:00 2001 From: sfu5 Date: Tue, 27 Mar 2012 08:17:23 +0000 Subject: [PATCH] =?utf8?q?1.=20Remove=20=E2=80=9CForce=20clear=20PK?= =?utf8?q?=E2=80=9D=20feature=20in=20AuthVarialbe=20driver.=202.=20Update?= =?utf8?q?=20API=20ForceClearPK()=20to=20UserPhysicalPresent()=20in=20Plat?= =?utf8?q?formSecureLib.=202.=20Update=20SecureBootConfigDxe=20driver=20an?= =?utf8?q?d=20AuthVariable=20driver=20to=20support=20Custom=20Secure=20Boo?= =?utf8?q?t=20Mode=20feature.=203.=20Fix=20some=20bugs=20in=20AuthVariable?= =?utf8?q?=20driver.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: sfu5 Reviewed-by: tye Reviewed-by: gdong1 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13144 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Guid/AuthenticatedVariableFormat.h | 16 +- .../Include/Library/PlatformSecureLib.h | 26 +- .../PlatformSecureLibNull.c | 28 +- .../PlatformSecureLibNull.inf | 2 +- SecurityPkg/SecurityPkg.dec | 5 +- .../RuntimeDxe/AuthService.c | 305 ++- .../RuntimeDxe/Variable.c | 65 +- .../RuntimeDxe/Variable.h | 20 +- .../RuntimeDxe/VariableRuntimeDxe.inf | 3 +- .../RuntimeDxe/VariableSmm.inf | 3 +- .../SecureBootConfigDxe/SecureBootConfig.vfr | 453 ++- .../SecureBootConfigDevicePath.c | 1537 +++++++++++ .../SecureBootConfigDxe.inf | 38 +- .../SecureBootConfigFileExplorer.c | 1227 +++++++++ .../SecureBootConfigImpl.c | 2438 ++++++++++++++++- .../SecureBootConfigImpl.h | 434 ++- .../SecureBootConfigMisc.c | 334 +++ .../SecureBootConfigNvData.h | 96 +- .../SecureBootConfigStrings.uni | Bin 2054 -> 9518 bytes 19 files changed, 6771 insertions(+), 259 deletions(-) create mode 100644 SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDevicePath.c create mode 100644 SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigFileExplorer.c create mode 100644 SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigMisc.c diff --git a/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h b/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h index 7ff469779c..7e543ee911 100644 --- a/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h +++ b/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h @@ -4,7 +4,7 @@ AuthenticatedVariableFormat.h defines variable data headers and variable storage region headers. -Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2012, 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 @@ -35,6 +35,20 @@ extern EFI_GUID gEfiSecureBootEnableDisableGuid; #define SECURE_BOOT_ENABLE 1 #define SECURE_BOOT_DISABLE 0 +extern EFI_GUID gEfiCustomModeEnableGuid; + +/// +/// "CustomMode" variable for two Secure Boot modes feature: "Custom" and "Standard". +/// Standard Secure Boot mode is the default mode as UEFI Spec's description. +/// Custom Secure Boot mode allows for more flexibility as specified in the following: +/// Can enroll or delete PK without existing PK's private key. +/// Can enroll or delete KEK without existing PK's private key. +/// Can enroll or delete signature from DB/DBX without KEK's private key. +/// +#define EFI_CUSTOM_MODE_NAME L"CustomMode" +#define CUSTOM_SECURE_BOOT_MODE 1 +#define STANDARD_SECURE_BOOT_MODE 0 + /// /// Alignment of variable name and data, according to the architecture: /// * For IA-32 and Intel(R) 64 architectures: 1. diff --git a/SecurityPkg/Include/Library/PlatformSecureLib.h b/SecurityPkg/Include/Library/PlatformSecureLib.h index c544719ba2..6a4cb147a6 100644 --- a/SecurityPkg/Include/Library/PlatformSecureLib.h +++ b/SecurityPkg/Include/Library/PlatformSecureLib.h @@ -1,7 +1,7 @@ /** @file - Provides a secure platform-specific method to clear PK(Platform Key). + Provides a secure platform-specific method to detect physically present user. -Copyright (c) 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2011 - 2012, 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 @@ -18,25 +18,25 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. /** - This function detects whether a secure platform-specific method to clear PK(Platform Key) - is configured by platform owner. This method is provided for users force to clear PK - in case incorrect enrollment mis-haps. - - UEFI231 spec chapter 27.5.2 stipulates: The platform key may also be cleared using - a secure platform-specific method. In this case, the global variable SetupMode - must also be updated to 1. + This function provides a platform-specific method to detect whether the platform + is operating by a physically present user. + + Programmatic changing of platform security policy (such as disable Secure Boot, + or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during + Boot Services or after exiting EFI Boot Services. Only a physically present user + is allowed to perform these operations. NOTE THAT: This function cannot depend on any EFI Variable Service since they are not available when this function is called in AuthenticateVariable driver. - @retval TRUE The Platform owner wants to force clear PK. - @retval FALSE The Platform owner doesn't want to force clear PK. + @retval TRUE The platform is operated by a physically present user. + @retval FALSE The platform is NOT operated by a physically present user. **/ BOOLEAN EFIAPI -ForceClearPK ( +UserPhysicalPresent ( VOID ); -#endif \ No newline at end of file +#endif diff --git a/SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.c b/SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.c index f085d62b77..cfce97e284 100644 --- a/SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.c +++ b/SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.c @@ -1,7 +1,7 @@ /** @file - Provides a secure platform-specific method to clear PK(Platform Key). + Provides a secure platform-specific method to detect physically present user. -Copyright (c) 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2011 - 2012, 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 @@ -14,24 +14,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. /** - This function detects whether a secure platform-specific method to clear PK(Platform Key) - is configured by platform owner. This method is provided for users force to clear PK - in case incorrect enrollment mis-haps. - - UEFI231 spec chapter 27.5.2 stipulates: The platform key may also be cleared using - a secure platform-specific method. In this case, the global variable SetupMode - must also be updated to 1. - + This function provides a platform-specific method to detect whether the platform + is operating by a physically present user. + + Programmatic changing of platform security policy (such as disable Secure Boot, + or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during + Boot Services or after exiting EFI Boot Services. Only a physically present user + is allowed to perform these operations. + NOTE THAT: This function cannot depend on any EFI Variable Service since they are not available when this function is called in AuthenticateVariable driver. - - @retval TRUE The Platform owner wants to force clear PK. - @retval FALSE The Platform owner doesn't want to force clear PK. + + @retval TRUE The platform is operated by a physically present user. + @retval FALSE The platform is NOT operated by a physically present user. **/ BOOLEAN EFIAPI -ForceClearPK ( +UserPhysicalPresent ( VOID ) { diff --git a/SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf b/SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf index dc119f2b1c..ce0b2cebcf 100644 --- a/SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf +++ b/SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf @@ -1,5 +1,5 @@ ## @file -# Provides a secure platform-specific method to clear PK(Platform Key). +# Provides a secure platform-specific method to detect physically present user. # # Copyright (c) 2011, Intel Corporation. All rights reserved.
# This program and the accompanying materials diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec index f9382788fc..e5471778ee 100644 --- a/SecurityPkg/SecurityPkg.dec +++ b/SecurityPkg/SecurityPkg.dec @@ -2,7 +2,7 @@ # This package includes the security drivers, defintions(including PPIs/PROTOCOLs/GUIDs # and library classes) and libraries instances. # -# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2012, 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 @@ -37,6 +37,9 @@ # Include/Guid/AuthenticatedVariableFormat.h gEfiSecureBootEnableDisableGuid = { 0xf0a30bc7, 0xaf08, 0x4556, { 0x99, 0xc4, 0x0, 0x10, 0x9, 0xc9, 0x3a, 0x44 } } + + # Include/Guid/AuthenticatedVariableFormat.h + gEfiCustomModeEnableGuid = { 0xc076ec0c, 0x7028, 0x4399, { 0xa0, 0x72, 0x71, 0xee, 0x5c, 0x44, 0x8b, 0x9f } } ## Include/Guid/TcgEventHob.h gTcgEventEntryHobGuid = { 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 }} diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c index f7a9888ce1..4036885570 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c @@ -2,7 +2,7 @@ Implement authentication services for the authenticated variable service in UEFI2.2. -Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2012, 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 @@ -65,6 +65,53 @@ EFI_SIGNATURE_ITEM mSupportSigItem[] = { {EFI_CERT_SHA512_GUID, 0, 64 } }; +/** + Determine whether this operation needs a physical present user. + + @param[in] VariableName Name of the Variable. + @param[in] VendorGuid GUID of the Variable. + + @retval TRUE This variable is protected, only a physical present user could set this variable. + @retval FALSE This variable is not protected. + +**/ +BOOLEAN +NeedPhysicallyPresent( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ) +{ + if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0)) + || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) { + return TRUE; + } + + return FALSE; +} + +/** + Determine whether the platform is operating in Custom Secure Boot mode. + + @retval TRUE The platform is operating in Custom mode. + @retval FALSE The platform is operating in Standard mode. + +**/ +BOOLEAN +InCustomMode ( + VOID + ) +{ + VARIABLE_POINTER_TRACK Variable; + + FindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); + if (Variable.CurrPtr != NULL && *(GetVariableDataPtr (Variable.CurrPtr)) == CUSTOM_SECURE_BOOT_MODE) { + return TRUE; + } + + return FALSE; +} + + /** Internal function to delete a Variable given its name and GUID, no authentication required. @@ -85,7 +132,7 @@ DeleteVariable ( EFI_STATUS Status; VARIABLE_POINTER_TRACK Variable; - Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); + Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); if (EFI_ERROR (Status)) { return EFI_SUCCESS; } @@ -116,6 +163,7 @@ AutenticatedVariableServiceInitialize ( UINTN CtxSize; UINT8 SecureBootMode; UINT8 SecureBootEnable; + UINT8 CustomMode; // // Initialize hash context. @@ -151,7 +199,8 @@ AutenticatedVariableServiceInitialize ( AUTHVAR_KEYDB_NAME, &gEfiAuthenticatedVariableGuid, &Variable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); if (Variable.CurrPtr == NULL) { @@ -183,7 +232,7 @@ AutenticatedVariableServiceInitialize ( mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE); } - FindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, &PkVariable, &mVariableModuleGlobal->VariableGlobal); + FindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, &PkVariable, &mVariableModuleGlobal->VariableGlobal, FALSE); if (PkVariable.CurrPtr == NULL) { DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME)); } else { @@ -199,7 +248,8 @@ AutenticatedVariableServiceInitialize ( EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); if (Variable.CurrPtr == NULL) { @@ -235,7 +285,8 @@ AutenticatedVariableServiceInitialize ( EFI_SIGNATURE_SUPPORT_NAME, &gEfiGlobalVariableGuid, &Variable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); if (Variable.CurrPtr == NULL) { @@ -259,7 +310,7 @@ AutenticatedVariableServiceInitialize ( // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE. // SecureBootEnable = SECURE_BOOT_MODE_DISABLE; - FindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); + FindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); if (Variable.CurrPtr != NULL) { SecureBootEnable = *(GetVariableDataPtr (Variable.CurrPtr)); } else if (mPlatformMode == USER_MODE) { @@ -288,7 +339,7 @@ AutenticatedVariableServiceInitialize ( } else { SecureBootMode = SECURE_BOOT_MODE_DISABLE; } - FindVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); + FindVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); Status = UpdateVariable ( EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, @@ -309,33 +360,33 @@ AutenticatedVariableServiceInitialize ( DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable)); // - // Detect whether a secure platform-specific method to clear PK(Platform Key) - // is configured by platform owner. This method is provided for users force to clear PK - // in case incorrect enrollment mis-haps. + // Check "CustomMode" variable's existence. // - if (ForceClearPK ()) { - DEBUG ((EFI_D_INFO, "Variable PK/KEK/DB/DBX will be cleared in clear PK mode.\n")); - + FindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); + if (Variable.CurrPtr != NULL) { + CustomMode = *(GetVariableDataPtr (Variable.CurrPtr)); + } else { // - // 1. Clear PK. + // "CustomMode" not exist, initialize it in STANDARD_SECURE_BOOT_MODE. // - Status = DeleteVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid); + CustomMode = STANDARD_SECURE_BOOT_MODE; + Status = UpdateVariable ( + EFI_CUSTOM_MODE_NAME, + &gEfiCustomModeEnableGuid, + &CustomMode, + sizeof (UINT8), + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, + 0, + &Variable, + NULL + ); if (EFI_ERROR (Status)) { return Status; } - - // - // 2. Update "SetupMode" variable to SETUP_MODE. - // - UpdatePlatformMode (SETUP_MODE); - - // - // 3. Clear KEK, DB and DBX. - // - DeleteVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid); - DeleteVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid); - DeleteVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid); } + + DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME, CustomMode)); return Status; } @@ -367,7 +418,8 @@ AddPubKeyInStore ( AUTHVAR_KEYDB_NAME, &gEfiAuthenticatedVariableGuid, &Variable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); ASSERT_EFI_ERROR (Status); // @@ -551,7 +603,8 @@ UpdatePlatformMode ( EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); if (EFI_ERROR (Status)) { return Status; @@ -592,7 +645,8 @@ UpdatePlatformMode ( EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); // // If "SecureBoot" variable exists, then check "SetupMode" variable update. @@ -634,7 +688,8 @@ UpdatePlatformMode ( EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, &Variable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); if (SecureBootMode == SECURE_BOOT_MODE_ENABLE) { @@ -811,7 +866,7 @@ ProcessVarWithPk ( return EFI_INVALID_PARAMETER; } - if (mPlatformMode == USER_MODE) { + if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) { if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { // @@ -860,7 +915,8 @@ ProcessVarWithPk ( EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, &PkVariable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); ASSERT_EFI_ERROR (Status); @@ -901,7 +957,7 @@ ProcessVarWithPk ( } } else { // - // Process PK or KEK in Setup mode. + // Process PK or KEK in Setup mode or Custom Secure Boot mode. // if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { // @@ -945,12 +1001,20 @@ ProcessVarWithPk ( Variable, TimeStamp ); - // - // If enroll PK in setup mode, need change to user mode. - // - if ((DataSize != 0) && IsPk) { - Status = UpdatePlatformMode (USER_MODE); - } + + if (IsPk) { + if (PayloadSize != 0) { + // + // If enroll PK in setup mode, need change to user mode. + // + Status = UpdatePlatformMode (USER_MODE); + } else { + // + // If delete PK in custom mode, need change to setup mode. + // + UpdatePlatformMode (SETUP_MODE); + } + } } return Status; @@ -996,85 +1060,116 @@ ProcessVarWithKek ( UINT8 *Payload; UINTN PayloadSize; UINT64 MonotonicCount; + EFI_TIME *TimeStamp; + + if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) { + // + // DB and DBX should set EFI_VARIABLE_NON_VOLATILE attribute. + // + return EFI_INVALID_PARAMETER; + } - if (mPlatformMode == USER_MODE) { - if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) { + Status = EFI_SUCCESS; + if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) { + if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) && + ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0)){ // - // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute. + // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS or + // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute. // return EFI_INVALID_PARAMETER; } - CertData = (EFI_VARIABLE_AUTHENTICATION *) Data; - CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData); - if ((Variable->CurrPtr != NULL) && (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount)) { + if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { // - // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION. + // Time-based, verify against X509 Cert KEK. // - return EFI_SECURITY_VIOLATION; - } - // - // Get KEK database from variable. - // - Status = FindVariable ( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - &KekVariable, - &mVariableModuleGlobal->VariableGlobal - ); - ASSERT_EFI_ERROR (Status); + return VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, FALSE, NULL); + } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) { + // + // Counter-based, verify against RSA2048 Cert KEK. + // + CertData = (EFI_VARIABLE_AUTHENTICATION *) Data; + CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData); + if ((Variable->CurrPtr != NULL) && (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount)) { + // + // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION. + // + return EFI_SECURITY_VIOLATION; + } + // + // Get KEK database from variable. + // + Status = FindVariable ( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + &KekVariable, + &mVariableModuleGlobal->VariableGlobal, + FALSE + ); + ASSERT_EFI_ERROR (Status); - KekDataSize = KekVariable.CurrPtr->DataSize; - KekList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (KekVariable.CurrPtr); + KekDataSize = KekVariable.CurrPtr->DataSize; + KekList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (KekVariable.CurrPtr); - // - // Enumerate all Kek items in this list to verify the variable certificate data. - // If anyone is authenticated successfully, it means the variable is correct! - // - IsFound = FALSE; - while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) { - if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) { - KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize); - KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize; - for (Index = 0; Index < KekCount; Index++) { - if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) { - IsFound = TRUE; - break; + // + // Enumerate all Kek items in this list to verify the variable certificate data. + // If anyone is authenticated successfully, it means the variable is correct! + // + IsFound = FALSE; + while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) { + if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) { + KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize); + KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize; + for (Index = 0; Index < KekCount; Index++) { + if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) { + IsFound = TRUE; + break; + } + KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize); } - KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize); } + KekDataSize -= KekList->SignatureListSize; + KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize); } - KekDataSize -= KekList->SignatureListSize; - KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize); - } - if (!IsFound) { - return EFI_SECURITY_VIOLATION; - } + if (!IsFound) { + return EFI_SECURITY_VIOLATION; + } - Status = VerifyCounterBasedPayload (Data, DataSize, CertBlock->PublicKey); - if (!EFI_ERROR (Status)) { - Status = UpdateVariable ( - VariableName, - VendorGuid, - (UINT8*)Data + AUTHINFO_SIZE, - DataSize - AUTHINFO_SIZE, - Attributes, - 0, - CertData->MonotonicCount, - Variable, - NULL - ); + Status = VerifyCounterBasedPayload (Data, DataSize, CertBlock->PublicKey); + if (!EFI_ERROR (Status)) { + Status = UpdateVariable ( + VariableName, + VendorGuid, + (UINT8*)Data + AUTHINFO_SIZE, + DataSize - AUTHINFO_SIZE, + Attributes, + 0, + CertData->MonotonicCount, + Variable, + NULL + ); + } } } else { // - // If in setup mode, no authentication needed. + // If in setup mode or custom secure boot mode, no authentication needed. // - if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) { + if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { + // + // Time-based Authentication descriptor. + // + MonotonicCount = 0; + TimeStamp = &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp; + Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data); + PayloadSize = DataSize - AUTHINFO2_SIZE (Data); + } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) { // // Counter-based Authentication descriptor. // MonotonicCount = ((EFI_VARIABLE_AUTHENTICATION *) Data)->MonotonicCount; + TimeStamp = NULL; Payload = (UINT8*) Data + AUTHINFO_SIZE; PayloadSize = DataSize - AUTHINFO_SIZE; } else { @@ -1082,6 +1177,7 @@ ProcessVarWithKek ( // No Authentication descriptor. // MonotonicCount = 0; + TimeStamp = NULL; Payload = Data; PayloadSize = DataSize; } @@ -1095,7 +1191,7 @@ ProcessVarWithKek ( 0, MonotonicCount, Variable, - NULL + TimeStamp ); } @@ -1148,6 +1244,13 @@ ProcessVariable ( PubKey = NULL; IsDeletion = FALSE; + if (NeedPhysicallyPresent(VariableName, VendorGuid) && !UserPhysicalPresent()) { + // + // This variable is protected, only physical present user could modify its value. + // + return EFI_SECURITY_VIOLATION; + } + // // Process Time-based Authenticated variable. // @@ -1538,7 +1641,8 @@ VerifyTimeBasedPayload ( EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, &PkVariable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); if (EFI_ERROR (Status)) { return Status; @@ -1571,7 +1675,8 @@ VerifyTimeBasedPayload ( EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &KekVariable, - &mVariableModuleGlobal->VariableGlobal + &mVariableModuleGlobal->VariableGlobal, + FALSE ); if (EFI_ERROR (Status)) { return Status; diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c index c84a2f62d3..22ded16819 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c @@ -718,17 +718,19 @@ Reclaim ( /** Find the variable in the specified variable store. - @param VariableName Name of the variable to be found - @param VendorGuid Vendor GUID to be found. - @param PtrTrack Variable Track Pointer structure that contains Variable Information. + @param[in] VariableName Name of the variable to be found + @param[in] VendorGuid Vendor GUID to be found. + @param[in] IgnoreRtAttribute Ignore RUNTIME_ACCESS attribute when searching variable. + @param[in, out] PtrTrack Variable Track Pointer structure that contains Variable Information. - @retval EFI_SUCCESS Variable found successfully - @retval EFI_NOT_FOUND Variable not found + @retval EFI_SUCCESS Variable found successfully + @retval EFI_NOT_FOUND Variable not found **/ EFI_STATUS FindVariableEx ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, + IN BOOLEAN IgnoreRtAttribute, IN OUT VARIABLE_POINTER_TRACK *PtrTrack ) { @@ -747,7 +749,7 @@ FindVariableEx ( if (PtrTrack->CurrPtr->State == VAR_ADDED || PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED) ) { - if (!AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) { + if (IgnoreRtAttribute || !AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) { if (VariableName[0] == 0) { if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { InDeletedVariable = PtrTrack->CurrPtr; @@ -783,15 +785,18 @@ FindVariableEx ( This code finds variable in storage blocks of volatile and non-volatile storage areas. If VariableName is an empty string, then we just return the first qualified variable without comparing VariableName and VendorGuid. - Otherwise, VariableName and VendorGuid are compared. + If IgnoreRtAttribute is TRUE, then we ignore the EFI_VARIABLE_RUNTIME_ACCESS Attribute + when searching existing variable, only VariableName and VendorGuid are compared. + Otherwise, variables with EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime. - @param VariableName Name of the variable to be found. - @param VendorGuid Vendor GUID to be found. - @param PtrTrack VARIABLE_POINTER_TRACK structure for output, + @param[in] VariableName Name of the variable to be found. + @param[in] VendorGuid Vendor GUID to be found. + @param[out] PtrTrack VARIABLE_POINTER_TRACK structure for output, including the range searched and the target position. - @param Global Pointer to VARIABLE_GLOBAL structure, including + @param[in] Global Pointer to VARIABLE_GLOBAL structure, including base of volatile variable storage area, base of NV variable storage area, and a lock. + @param[in] IgnoreRtAttribute Ignore RUNTIME_ACCESS attribute when searching variable. @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while VendorGuid is NULL. @@ -804,7 +809,8 @@ FindVariable ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT VARIABLE_POINTER_TRACK *PtrTrack, - IN VARIABLE_GLOBAL *Global + IN VARIABLE_GLOBAL *Global, + IN BOOLEAN IgnoreRtAttribute ) { EFI_STATUS Status; @@ -836,7 +842,7 @@ FindVariable ( PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Type]); PtrTrack->Volatile = (BOOLEAN) (Type == VariableStoreTypeVolatile); - Status = FindVariableEx (VariableName, VendorGuid, PtrTrack); + Status = FindVariableEx (VariableName, VendorGuid, IgnoreRtAttribute, PtrTrack); if (!EFI_ERROR (Status)) { return Status; } @@ -1238,7 +1244,7 @@ AutoUpdateLangVariable ( // Update Lang if PlatformLang is already set // Update PlatformLang if Lang is already set // - Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); + Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); if (!EFI_ERROR (Status)) { // // Update Lang @@ -1247,7 +1253,7 @@ AutoUpdateLangVariable ( Data = GetVariableDataPtr (Variable.CurrPtr); DataSize = Variable.CurrPtr->DataSize; } else { - Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); + Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); if (!EFI_ERROR (Status)) { // // Update PlatformLang @@ -1292,7 +1298,7 @@ AutoUpdateLangVariable ( // // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously. // - FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); + FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, 0, 0, &Variable, NULL); @@ -1326,7 +1332,7 @@ AutoUpdateLangVariable ( // // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously. // - FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); + FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang, AsciiStrSize (BestPlatformLang), Attributes, 0, 0, &Variable, NULL); @@ -1456,6 +1462,14 @@ UpdateVariable ( Status = EFI_INVALID_PARAMETER; goto Done; } + + // + // Only variable that have RT attributes can be updated/deleted in Runtime. + // + if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } } // @@ -1905,7 +1919,7 @@ VariableServiceGetVariable ( AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); - Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); + Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { goto Done; } @@ -1980,7 +1994,7 @@ VariableServiceGetNextVariableName ( AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); - Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); + Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { goto Done; } @@ -2057,6 +2071,7 @@ VariableServiceGetNextVariableName ( Status = FindVariableEx ( GetVariableNamePtr (Variable.CurrPtr), &Variable.CurrPtr->VendorGuid, + FALSE, &VariableInHob ); if (!EFI_ERROR (Status)) { @@ -2220,8 +2235,13 @@ VariableServiceSetVariable ( // // Check whether the input variable is already existed. // - FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal); - + Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, TRUE); + if (!EFI_ERROR (Status)) { + if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) { + return EFI_WRITE_PROTECTED; + } + } + // // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang. // @@ -2233,7 +2253,8 @@ VariableServiceSetVariable ( Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes, TRUE); } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) { Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes, FALSE); - } else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) && ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0)) { + } else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) && + ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))) { Status = ProcessVarWithKek (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes); } else { Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes); diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h index 58d1e5a8cd..d58203739f 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h @@ -2,7 +2,7 @@ The internal header file includes the common header files, defines internal structure and functions used by Variable modules. -Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2012, 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 @@ -120,20 +120,23 @@ FtwVariableSpace ( This code finds variable in storage blocks of volatile and non-volatile storage areas. If VariableName is an empty string, then we just return the first qualified variable without comparing VariableName and VendorGuid. - Otherwise, VariableName and VendorGuid are compared. + If IgnoreRtAttribute is TRUE, then we ignore the EFI_VARIABLE_RUNTIME_ACCESS Attribute + when searching existing variable, only VariableName and VendorGuid are compared. + Otherwise, variables with EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime. - @param VariableName Name of the variable to be found. - @param VendorGuid Vendor GUID to be found. - @param PtrTrack VARIABLE_POINTER_TRACK structure for output, + @param[in] VariableName Name of the variable to be found. + @param[in] VendorGuid Vendor GUID to be found. + @param[out] PtrTrack VARIABLE_POINTER_TRACK structure for output, including the range searched and the target position. - @param Global Pointer to VARIABLE_GLOBAL structure, including + @param[in] Global Pointer to VARIABLE_GLOBAL structure, including base of volatile variable storage area, base of NV variable storage area, and a lock. + @param[in] IgnoreRtAttribute Ignore RUNTIME_ACCESS attribute when searching variable. @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while VendorGuid is NULL. @retval EFI_SUCCESS Variable successfully found. - @retval EFI_INVALID_PARAMETER Variable not found. + @retval EFI_NOT_FOUND Variable not found **/ EFI_STATUS @@ -141,7 +144,8 @@ FindVariable ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT VARIABLE_POINTER_TRACK *PtrTrack, - IN VARIABLE_GLOBAL *Global + IN VARIABLE_GLOBAL *Global, + IN BOOLEAN IgnoreRtAttribute ); /** diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf index 70717c4573..abe14abab3 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf @@ -1,7 +1,7 @@ ## @file # Component description file for Authenticated Variable module. # -# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2012, 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 @@ -73,6 +73,7 @@ gEfiCertPkcs7Guid gEfiCertRsa2048Guid gEfiSecureBootEnableDisableGuid + gEfiCustomModeEnableGuid gEfiSystemNvDataFvGuid ## CONSUMES [Pcd] diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf index 84762dc406..cd6457f8f4 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf @@ -9,7 +9,7 @@ # SMM Runtime DXE module would install variable arch protocol and variable # write arch protocol based on SMM variable module. # -# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+# Copyright (c) 2010 - 2012, 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 @@ -78,6 +78,7 @@ gEfiCertPkcs7Guid gEfiCertRsa2048Guid gEfiSecureBootEnableDisableGuid + gEfiCustomModeEnableGuid gEfiSystemNvDataFvGuid ## CONSUMES [Pcd] diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr index fbf5e2eae1..22c03c1288 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr @@ -1,7 +1,7 @@ /** @file VFR file used by the SecureBoot configuration component. -Copyright (c) 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2011 - 2012, 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 @@ -24,26 +24,471 @@ formset varid = SECUREBOOT_CONFIGURATION_VARSTORE_ID, name = SECUREBOOT_CONFIGURATION, guid = SECUREBOOT_CONFIG_FORM_SET_GUID; - + + // + // ##1 Form "Secure Boot Configuration" + // form formid = SECUREBOOT_CONFIGURATION_FORM_ID, title = STRING_TOKEN(STR_SECUREBOOT_TITLE); subtitle text = STRING_TOKEN(STR_NULL); - + + // + // Define of Check Box: Attempt Secure Boot + // suppressif TRUE; checkbox varid = SECUREBOOT_CONFIGURATION.HideSecureBoot, prompt = STRING_TOKEN(STR_NULL), help = STRING_TOKEN(STR_NULL), endcheckbox; - endif; + endif; + // + // Display of Check Box: Attempt Secure Boot + // grayoutif ideqval SECUREBOOT_CONFIGURATION.HideSecureBoot == 1; checkbox varid = SECUREBOOT_CONFIGURATION.SecureBootState, questionid = KEY_SECURE_BOOT_ENABLE, prompt = STRING_TOKEN(STR_SECURE_BOOT_PROMPT), help = STRING_TOKEN(STR_SECURE_BOOT_HELP), + flags = INTERACTIVE, + endcheckbox; + endif; + + // + // Display of Oneof: 'Secure Boot Mode' + // + oneof varid = SECUREBOOT_CONFIGURATION.SecureBootMode, + questionid = KEY_SECURE_BOOT_MODE, + prompt = STRING_TOKEN(STR_SECURE_BOOT_MODE_PROMPT), + help = STRING_TOKEN(STR_SECURE_BOOT_MODE_HELP), + flags = INTERACTIVE, + option text = STRING_TOKEN(STR_STANDARD_MODE), value = SECURE_BOOT_MODE_STANDARD, flags = DEFAULT; + option text = STRING_TOKEN(STR_CUSTOM_MODE), value = SECURE_BOOT_MODE_CUSTOM, flags = 0; + endoneof; + + // + // + // Display of 'Current Secure Boot Mode' + // + suppressif ideqval SECUREBOOT_CONFIGURATION.SecureBootMode == SECURE_BOOT_MODE_STANDARD; + grayoutif NOT ideqval SECUREBOOT_CONFIGURATION.PhysicalPresent == 1; + goto FORMID_SECURE_BOOT_OPTION_FORM, + prompt = STRING_TOKEN(STR_SECURE_BOOT_OPTION), + help = STRING_TOKEN(STR_SECURE_BOOT_OPTION_HELP), + flags = INTERACTIVE, + key = KEY_SECURE_BOOT_OPTION; + endif; + endif; + endform; + + // + // ##2 Form: 'Custom Secure Boot Options' + // + form formid = FORMID_SECURE_BOOT_OPTION_FORM, + title = STRING_TOKEN(STR_SECURE_BOOT_OPTION_TITLE); + + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORMID_SECURE_BOOT_PK_OPTION_FORM, + prompt = STRING_TOKEN(STR_SECURE_BOOT_PK_OPTION), + help = STRING_TOKEN(STR_SECURE_BOOT_PK_OPTION_HELP), + flags = INTERACTIVE, + key = KEY_SECURE_BOOT_PK_OPTION; + + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORMID_SECURE_BOOT_KEK_OPTION_FORM, + prompt = STRING_TOKEN(STR_SECURE_BOOT_KEK_OPTION), + help = STRING_TOKEN(STR_SECURE_BOOT_KEK_OPTION_HELP), + flags = INTERACTIVE, + key = KEY_SECURE_BOOT_KEK_OPTION; + + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORMID_SECURE_BOOT_DB_OPTION_FORM, + prompt = STRING_TOKEN(STR_SECURE_BOOT_DB_OPTION), + help = STRING_TOKEN(STR_SECURE_BOOT_DB_OPTION_HELP), + flags = INTERACTIVE, + key = KEY_SECURE_BOOT_DB_OPTION; + + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORMID_SECURE_BOOT_DBX_OPTION_FORM, + prompt = STRING_TOKEN(STR_SECURE_BOOT_DBX_OPTION), + help = STRING_TOKEN(STR_SECURE_BOOT_DBX_OPTION_HELP), + flags = INTERACTIVE, + key = KEY_SECURE_BOOT_DBX_OPTION; + + endform; + + // + // ##3 Form: 'PK Options' + // + form formid = FORMID_SECURE_BOOT_PK_OPTION_FORM, + title = STRING_TOKEN(STR_SECURE_BOOT_PK_OPTION); + + subtitle text = STRING_TOKEN(STR_NULL); + + // + // Define of Check Box: 'Delete PK' + // + suppressif TRUE; + checkbox varid = SECUREBOOT_CONFIGURATION.DeletePk, + prompt = STRING_TOKEN(STR_NULL), + help = STRING_TOKEN(STR_NULL), + endcheckbox; + endif; + + grayoutif ideqval SECUREBOOT_CONFIGURATION.HasPk == 1; + goto FORMID_ENROLL_PK_FORM, + prompt = STRING_TOKEN(STR_ENROLL_PK), + help = STRING_TOKEN(STR_ENROLL_PK_HELP), + flags = INTERACTIVE, + key = KEY_ENROLL_PK; + endif; + + subtitle text = STRING_TOKEN(STR_NULL); + + // + // Display of Check Box: 'Delete Pk' + // + grayoutif ideqval SECUREBOOT_CONFIGURATION.HideSecureBoot == 1; + checkbox varid = SECUREBOOT_CONFIGURATION.DeletePk, + questionid = KEY_SECURE_BOOT_DELETE_PK, + prompt = STRING_TOKEN(STR_DELETE_PK), + help = STRING_TOKEN(STR_DELETE_PK_HELP), + flags = INTERACTIVE, endcheckbox; endif; + endform; + + // + // ##4 Form: 'Enroll PK' + // + form formid = FORMID_ENROLL_PK_FORM, + title = STRING_TOKEN(STR_ENROLL_PK); + + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORM_FILE_EXPLORER_ID_PK, + prompt = STRING_TOKEN(STR_SECURE_BOOT_ENROLL_PK_FILE), + help = STRING_TOKEN(STR_SECURE_BOOT_ENROLL_PK_FILE), + flags = INTERACTIVE, + key = SECUREBOOT_ADD_PK_FILE_FORM_ID; + endform; + + // + // ##5 Form: 'KEK Options' + // + form formid = FORMID_SECURE_BOOT_KEK_OPTION_FORM, + title = STRING_TOKEN(STR_SECURE_BOOT_KEK_OPTION); + + // + // Display of 'Enroll KEK' + // + goto FORMID_ENROLL_KEK_FORM, + prompt = STRING_TOKEN(STR_ENROLL_KEK), + help = STRING_TOKEN(STR_ENROLL_KEK_HELP), + flags = INTERACTIVE; + + subtitle text = STRING_TOKEN(STR_NULL); + + // + // Display of 'Delete KEK' + // + goto FORMID_DELETE_KEK_FORM, + prompt = STRING_TOKEN(STR_DELETE_KEK), + help = STRING_TOKEN(STR_DELETE_KEK_HELP), + flags = INTERACTIVE, + key = KEY_DELETE_KEK; + + subtitle text = STRING_TOKEN(STR_NULL); + endform; + + // + // ##6 Form: 'Enroll KEK' + // + form formid = FORMID_ENROLL_KEK_FORM, + title = STRING_TOKEN(STR_ENROLL_KEK_TITLE); + + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORM_FILE_EXPLORER_ID_KEK, + prompt = STRING_TOKEN(STR_FORM_ENROLL_KEK_FROM_FILE_TITLE), + help = STRING_TOKEN(STR_FORM_ENROLL_KEK_FROM_FILE_TITLE_HELP), + flags = INTERACTIVE, + key = FORMID_ENROLL_KEK_FORM; + + subtitle text = STRING_TOKEN(STR_NULL); + label FORMID_ENROLL_KEK_FORM; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_NULL); + + string varid = SECUREBOOT_CONFIGURATION.SignatureGuid, + prompt = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID), + help = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID_HELP), + flags = INTERACTIVE, + key = KEY_SECURE_BOOT_KEK_GUID, + minsize = SECURE_BOOT_GUID_SIZE, + maxsize = SECURE_BOOT_GUID_SIZE, + endstring; + + subtitle text = STRING_TOKEN(STR_NULL); + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORMID_SECURE_BOOT_OPTION_FORM, + prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + flags = INTERACTIVE, + key = KEY_VALUE_SAVE_AND_EXIT_KEK; + + goto FORMID_SECURE_BOOT_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_KEK; + + endform; + + // + // ##7 Form: 'Delete KEK' + // + form formid = FORMID_DELETE_KEK_FORM, + title = STRING_TOKEN(STR_DELETE_KEK_TITLE); + + label LABEL_KEK_DELETE; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_NULL); + + endform; + + // + // ##8 Form: 'DB Options' + // + form formid = FORMID_SECURE_BOOT_DB_OPTION_FORM, + title = STRING_TOKEN(STR_SECURE_BOOT_DB_OPTION); + + subtitle text = STRING_TOKEN(STR_NULL); + + goto SECUREBOOT_ENROLL_SIGNATURE_TO_DB, + prompt = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE), + help = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE), + flags = 0; + + subtitle text = STRING_TOKEN(STR_NULL); + + goto SECUREBOOT_DELETE_SIGNATURE_FROM_DB, + prompt = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE), + help = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE), + flags = INTERACTIVE, + key = SECUREBOOT_DELETE_SIGNATURE_FROM_DB; + + endform; + + // + // ##9 Form: 'DBX Options' + // + form formid = FORMID_SECURE_BOOT_DBX_OPTION_FORM, + title = STRING_TOKEN(STR_SECURE_BOOT_DBX_OPTION); + + subtitle text = STRING_TOKEN(STR_NULL); + + goto SECUREBOOT_ENROLL_SIGNATURE_TO_DBX, + prompt = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE), + help = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE), + flags = 0; + + subtitle text = STRING_TOKEN(STR_NULL); + + goto SECUREBOOT_DELETE_SIGNATURE_FROM_DBX, + prompt = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE), + help = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE), + flags = INTERACTIVE, + key = SECUREBOOT_DELETE_SIGNATURE_FROM_DBX; + + endform; + + // + // Form: 'Delete Signature' for DB Options. + // + form formid = SECUREBOOT_DELETE_SIGNATURE_FROM_DB, + title = STRING_TOKEN(STR_SECURE_BOOT_DELETE_SIGNATURE); + + label LABEL_DB_DELETE; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_NULL); + + endform; + + // + // Form: 'Delete Signature' for DBX Options. + // + form formid = SECUREBOOT_DELETE_SIGNATURE_FROM_DBX, + title = STRING_TOKEN(STR_SECURE_BOOT_DELETE_SIGNATURE); + + label LABEL_DBX_DELETE; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_NULL); + + endform; + + // + // Form: 'Enroll Signature' for DB options. + // + form formid = SECUREBOOT_ENROLL_SIGNATURE_TO_DB, + title = STRING_TOKEN(STR_SECURE_BOOT_ENROLL_SIGNATURE); + + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORM_FILE_EXPLORER_ID_DB, + prompt = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE), + help = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE), + flags = INTERACTIVE, + key = SECUREBOOT_ENROLL_SIGNATURE_TO_DB; + + subtitle text = STRING_TOKEN(STR_NULL); + label SECUREBOOT_ENROLL_SIGNATURE_TO_DB; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_NULL); + + string varid = SECUREBOOT_CONFIGURATION.SignatureGuid, + prompt = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID), + help = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID_HELP), + flags = INTERACTIVE, + key = KEY_SECURE_BOOT_SIGNATURE_GUID_DB, + minsize = SECURE_BOOT_GUID_SIZE, + maxsize = SECURE_BOOT_GUID_SIZE, + endstring; + + subtitle text = STRING_TOKEN(STR_NULL); + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORMID_SECURE_BOOT_OPTION_FORM, + prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + flags = INTERACTIVE, + key = KEY_VALUE_SAVE_AND_EXIT_DB; + + goto FORMID_SECURE_BOOT_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: 'Enroll Signature' for DBX options. + // + form formid = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX, + title = STRING_TOKEN(STR_SECURE_BOOT_ENROLL_SIGNATURE); + + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORM_FILE_EXPLORER_ID_DBX, + prompt = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE), + help = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE), + flags = INTERACTIVE, + key = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX; + + subtitle text = STRING_TOKEN(STR_NULL); + label SECUREBOOT_ENROLL_SIGNATURE_TO_DBX; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_NULL); + + string varid = SECUREBOOT_CONFIGURATION.SignatureGuid, + prompt = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID), + help = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID_HELP), + flags = INTERACTIVE, + key = KEY_SECURE_BOOT_SIGNATURE_GUID_DBX, + minsize = SECURE_BOOT_GUID_SIZE, + maxsize = SECURE_BOOT_GUID_SIZE, + endstring; + + subtitle text = STRING_TOKEN(STR_NULL); + subtitle text = STRING_TOKEN(STR_NULL); + + goto FORMID_SECURE_BOOT_OPTION_FORM, + prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + flags = INTERACTIVE, + key = KEY_VALUE_SAVE_AND_EXIT_DBX; + + goto FORMID_SECURE_BOOT_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; + + // + // File Explorer for PK + // + form formid = FORM_FILE_EXPLORER_ID_PK, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE); + + label FORM_FILE_EXPLORER_ID; + label LABEL_END; + endform; + + // + // File Explorer for KEK + // + form formid = FORM_FILE_EXPLORER_ID_KEK, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE); + + label FORM_FILE_EXPLORER_ID; + label LABEL_END; + endform; + + // + // File Explorer for DB + // + form formid = FORM_FILE_EXPLORER_ID_DB, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE); + + label FORM_FILE_EXPLORER_ID; + label LABEL_END; + endform; + + // + // File Explorer for DBX + // + form formid = FORM_FILE_EXPLORER_ID_DBX, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE); + + label FORM_FILE_EXPLORER_ID; + label LABEL_END; + endform; + + + // + // Enroll Pk from File Commit Form + // + form formid = SECUREBOOT_ADD_PK_FILE_FORM_ID, + title = STRING_TOKEN(STR_SAVE_PK_FILE); + + label SECUREBOOT_ADD_PK_FILE_FORM_ID; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_NULL); + + text + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL), + flags = INTERACTIVE, + key = KEY_VALUE_SAVE_AND_EXIT_PK; + + text + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL), + flags = INTERACTIVE, + key = KEY_VALUE_NO_SAVE_AND_EXIT_PK; endform; diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDevicePath.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDevicePath.c new file mode 100644 index 0000000000..ae44626594 --- /dev/null +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDevicePath.c @@ -0,0 +1,1537 @@ +/** @file + Internal function defines the default device path string for SecureBoot configuration module. + +Copyright (c) 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SecureBootConfigImpl.h" + +/** + Concatenates a formatted unicode string to allocated pool. + The caller must free the resulting buffer. + + @param[in, out] Str Tracks the allocated pool, size in use, and amount of pool allocated. + @param[in] Fmt The format string + @param[in] ... The data will be printed. + + @return Allocated buffer with the formatted string printed in it. + The caller must free the allocated buffer. + The buffer allocation is not packed. + +**/ +CHAR16 * +EFIAPI +CatPrint ( + IN OUT POOL_PRINT *Str, + IN CHAR16 *Fmt, + ... + ) +{ + UINT16 *AppendStr; + VA_LIST Args; + UINTN StringSize; + + AppendStr = AllocateZeroPool (0x1000); + if (AppendStr == NULL) { + return Str->Str; + } + + VA_START (Args, Fmt); + UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args); + VA_END (Args); + if (NULL == Str->Str) { + StringSize = StrSize (AppendStr); + Str->Str = AllocateZeroPool (StringSize); + ASSERT (Str->Str != NULL); + } else { + StringSize = StrSize (AppendStr); + StringSize += (StrSize (Str->Str) - sizeof (UINT16)); + + Str->Str = ReallocatePool ( + StrSize (Str->Str), + StringSize, + Str->Str + ); + ASSERT (Str->Str != NULL); + } + + Str->Maxlen = MAX_CHAR * sizeof (UINT16); + if (StringSize < Str->Maxlen) { + StrCat (Str->Str, AppendStr); + Str->Len = StringSize - sizeof (UINT16); + } + + FreePool (AppendStr); + return Str->Str; +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathPci ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + PCI_DEVICE_PATH *Pci; + + Pci = DevPath; + CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathPccard ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + PCCARD_DEVICE_PATH *Pccard; + + Pccard = DevPath; + CatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathMemMap ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEMMAP_DEVICE_PATH *MemMap; + + MemMap = DevPath; + CatPrint ( + Str, + L"MemMap(%d:%lx-%lx)", + (UINTN) MemMap->MemoryType, + MemMap->StartingAddress, + MemMap->EndingAddress + ); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathController ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CONTROLLER_DEVICE_PATH *Controller; + + Controller = DevPath; + CatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber); +} + + +/** + Convert Vendor device path to device name. + + @param[in, out] Str The buffer store device name + @param[in] DevPath Pointer to vendor device path + +**/ +VOID +DevPathVendor ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + VENDOR_DEVICE_PATH *Vendor; + CHAR16 *Type; + UINTN DataLength; + UINTN Index; + UINT32 FlowControlMap; + + UINT16 Info; + + Vendor = DevPath; + + switch (DevicePathType (&Vendor->Header)) { + case HARDWARE_DEVICE_PATH: + Type = L"Hw"; + break; + + case MESSAGING_DEVICE_PATH: + Type = L"Msg"; + if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) { + CatPrint (Str, L"VenPcAnsi()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) { + CatPrint (Str, L"VenVt100()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) { + CatPrint (Str, L"VenVt100Plus()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) { + CatPrint (Str, L"VenUft8()"); + return ; + } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid )) { + FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap); + switch (FlowControlMap & 0x00000003) { + case 0: + CatPrint (Str, L"UartFlowCtrl(%s)", L"None"); + break; + + case 1: + CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware"); + break; + + case 2: + CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff"); + break; + + default: + break; + } + + return ; + + } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) { + CatPrint ( + Str, + L"SAS(%lx,%lx,%x,", + ((SAS_DEVICE_PATH *) Vendor)->SasAddress, + ((SAS_DEVICE_PATH *) Vendor)->Lun, + (UINTN) ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort + ); + Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology); + if ((Info & 0x0f) == 0) { + CatPrint (Str, L"NoTopology,0,0,0,"); + } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) { + CatPrint ( + Str, + L"%s,%s,%s,", + ((Info & (0x1 << 4)) != 0) ? L"SATA" : L"SAS", + ((Info & (0x1 << 5)) != 0) ? L"External" : L"Internal", + ((Info & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct" + ); + if ((Info & 0x0f) == 1) { + CatPrint (Str, L"0,"); + } else { + CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff)); + } + } else { + CatPrint (Str, L"0,0,0,0,"); + } + + CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved); + return ; + + } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) { + CatPrint (Str, L"DebugPort()"); + return ; + } + break; + + case MEDIA_DEVICE_PATH: + Type = L"Media"; + break; + + default: + Type = L"?"; + break; + } + + CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid); + DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH); + if (DataLength > 0) { + CatPrint (Str, L","); + for (Index = 0; Index < DataLength; Index++) { + CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]); + } + } + CatPrint (Str, L")"); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + Acpi = DevPath; + if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN) EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID); + } else { + CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID); + } +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathExtendedAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi; + + // + // Index for HID, UID and CID strings, 0 for non-exist + // + UINT16 HIDSTRIdx; + UINT16 UIDSTRIdx; + UINT16 CIDSTRIdx; + UINT16 Index; + UINT16 Length; + UINT16 Anchor; + CHAR8 *AsChar8Array; + + HIDSTRIdx = 0; + UIDSTRIdx = 0; + CIDSTRIdx = 0; + ExtendedAcpi = DevPath; + Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi); + + AsChar8Array = (CHAR8 *) ExtendedAcpi; + + // + // find HIDSTR + // + Anchor = 16; + for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) { + ; + } + if (Index > Anchor) { + HIDSTRIdx = Anchor; + } + // + // find UIDSTR + // + Anchor = (UINT16) (Index + 1); + for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) { + ; + } + if (Index > Anchor) { + UIDSTRIdx = Anchor; + } + // + // find CIDSTR + // + Anchor = (UINT16) (Index + 1); + for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) { + ; + } + if (Index > Anchor) { + CIDSTRIdx = Anchor; + } + + if (HIDSTRIdx == 0 && CIDSTRIdx == 0 && ExtendedAcpi->UID == 0) { + CatPrint (Str, L"AcpiExp("); + if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID)); + } else { + CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID); + } + if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID)); + } else { + CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID); + } + if (UIDSTRIdx != 0) { + CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx); + } else { + CatPrint (Str, L"\"\")"); + } + } else { + CatPrint (Str, L"AcpiEx("); + if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID)); + } else { + CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID); + } + if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID)); + } else { + CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID); + } + CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID); + + if (HIDSTRIdx != 0) { + CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx); + } else { + CatPrint (Str, L"\"\","); + } + if (CIDSTRIdx != 0) { + CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx); + } else { + CatPrint (Str, L"\"\","); + } + if (UIDSTRIdx != 0) { + CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx); + } else { + CatPrint (Str, L"\"\")"); + } + } + +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathAdrAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + ACPI_ADR_DEVICE_PATH *AcpiAdr; + UINT16 Index; + UINT16 Length; + UINT16 AdditionalAdrCount; + + AcpiAdr = DevPath; + Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr); + AdditionalAdrCount = (UINT16) ((Length - 8) / 4); + + CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR); + for (Index = 0; Index < AdditionalAdrCount; Index++) { + CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4)); + } + CatPrint (Str, L")"); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathAtapi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + ATAPI_DEVICE_PATH *Atapi; + + Atapi = DevPath; + CatPrint ( + Str, + L"Ata(%s,%s)", + (Atapi->PrimarySecondary != 0)? L"Secondary" : L"Primary", + (Atapi->SlaveMaster != 0)? L"Slave" : L"Master" + ); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathScsi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + SCSI_DEVICE_PATH *Scsi; + + Scsi = DevPath; + CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathFibre ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + FIBRECHANNEL_DEVICE_PATH *Fibre; + + Fibre = DevPath; + CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPath1394 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + F1394_DEVICE_PATH *F1394Path; + + F1394Path = DevPath; + CatPrint (Str, L"1394(%lx)", &F1394Path->Guid); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathUsb ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + USB_DEVICE_PATH *Usb; + + Usb = DevPath; + CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathUsbWWID ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + USB_WWID_DEVICE_PATH *UsbWWId; + + UsbWWId = DevPath; + CatPrint ( + Str, + L"UsbWwid(%x,%x,%x,\"WWID\")", + (UINTN) UsbWWId->VendorId, + (UINTN) UsbWWId->ProductId, + (UINTN) UsbWWId->InterfaceNumber + ); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathLogicalUnit ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit; + + LogicalUnit = DevPath; + CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathUsbClass ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + USB_CLASS_DEVICE_PATH *UsbClass; + + UsbClass = DevPath; + CatPrint ( + Str, + L"Usb Class(%x,%x,%x,%x,%x)", + (UINTN) UsbClass->VendorId, + (UINTN) UsbClass->ProductId, + (UINTN) UsbClass->DeviceClass, + (UINTN) UsbClass->DeviceSubClass, + (UINTN) UsbClass->DeviceProtocol + ); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathSata ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + SATA_DEVICE_PATH *Sata; + + Sata = DevPath; + if ((Sata->PortMultiplierPortNumber & SATA_HBA_DIRECT_CONNECT_FLAG) != 0) { + CatPrint ( + Str, + L"Sata(%x,%x)", + (UINTN) Sata->HBAPortNumber, + (UINTN) Sata->Lun + ); + } else { + CatPrint ( + Str, + L"Sata(%x,%x,%x)", + (UINTN) Sata->HBAPortNumber, + (UINTN) Sata->PortMultiplierPortNumber, + (UINTN) Sata->Lun + ); + } +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathI2O ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + I2O_DEVICE_PATH *I2OPath; + + I2OPath = DevPath; + CatPrint (Str, L"I2O(%x)", (UINTN) I2OPath->Tid); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathMacAddr ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MAC_ADDR_DEVICE_PATH *MACDevPath; + UINTN HwAddressSize; + UINTN Index; + + MACDevPath = DevPath; + + HwAddressSize = sizeof (EFI_MAC_ADDRESS); + if (MACDevPath->IfType == 0x01 || MACDevPath->IfType == 0x00) { + HwAddressSize = 6; + } + + CatPrint (Str, L"Mac("); + + for (Index = 0; Index < HwAddressSize; Index++) { + CatPrint (Str, L"%02x", (UINTN) MACDevPath->MacAddress.Addr[Index]); + } + + CatPrint (Str, L")"); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathIPv4 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + IPv4_DEVICE_PATH *IPDevPath; + + IPDevPath = DevPath; + CatPrint ( + Str, + L"IPv4(%d.%d.%d.%d:%d)", + (UINTN) IPDevPath->RemoteIpAddress.Addr[0], + (UINTN) IPDevPath->RemoteIpAddress.Addr[1], + (UINTN) IPDevPath->RemoteIpAddress.Addr[2], + (UINTN) IPDevPath->RemoteIpAddress.Addr[3], + (UINTN) IPDevPath->RemotePort + ); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathIPv6 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + IPv6_DEVICE_PATH *IPv6DevPath; + + IPv6DevPath = DevPath; + CatPrint ( + Str, + L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)", + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[0], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[1], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[2], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[3], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[4], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[5], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[6], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[7], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[8], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[9], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[10], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[11], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[12], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[13], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[14], + (UINTN) IPv6DevPath->RemoteIpAddress.Addr[15] + ); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathInfiniBand ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + INFINIBAND_DEVICE_PATH *InfiniBand; + + InfiniBand = DevPath; + CatPrint ( + Str, + L"Infiniband(%x,%g,%lx,%lx,%lx)", + (UINTN) InfiniBand->ResourceFlags, + InfiniBand->PortGid, + InfiniBand->ServiceId, + InfiniBand->TargetPortId, + InfiniBand->DeviceId + ); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathUart ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + UART_DEVICE_PATH *Uart; + CHAR8 Parity; + + Uart = DevPath; + switch (Uart->Parity) { + case 0: + Parity = 'D'; + break; + + case 1: + Parity = 'N'; + break; + + case 2: + Parity = 'E'; + break; + + case 3: + Parity = 'O'; + break; + + case 4: + Parity = 'M'; + break; + + case 5: + Parity = 'S'; + break; + + default: + Parity = 'x'; + break; + } + + if (Uart->BaudRate == 0) { + CatPrint (Str, L"Uart(DEFAULT,%c,", Parity); + } else { + CatPrint (Str, L"Uart(%ld,%c,", Uart->BaudRate, Parity); + } + + if (Uart->DataBits == 0) { + CatPrint (Str, L"D,"); + } else { + CatPrint (Str, L"%d,", (UINTN) Uart->DataBits); + } + + switch (Uart->StopBits) { + case 0: + CatPrint (Str, L"D)"); + break; + + case 1: + CatPrint (Str, L"1)"); + break; + + case 2: + CatPrint (Str, L"1.5)"); + break; + + case 3: + CatPrint (Str, L"2)"); + break; + + default: + CatPrint (Str, L"x)"); + break; + } +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathiSCSI ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + ISCSI_DEVICE_PATH_WITH_NAME *IScsi; + UINT16 Options; + + IScsi = DevPath; + CatPrint ( + Str, + L"iSCSI(%a,%x,%lx,", + IScsi->TargetName, + (UINTN) IScsi->TargetPortalGroupTag, + IScsi->Lun + ); + + Options = IScsi->LoginOption; + CatPrint (Str, L"%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None"); + CatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None"); + if (((Options >> 11) & 0x0001) != 0) { + CatPrint (Str, L"%s,", L"None"); + } else if (((Options >> 12) & 0x0001) != 0) { + CatPrint (Str, L"%s,", L"CHAP_UNI"); + } else { + CatPrint (Str, L"%s,", L"CHAP_BI"); + + } + + CatPrint (Str, L"%s)", (IScsi->NetworkProtocol == 0) ? L"TCP" : L"reserved"); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathVlan ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + VLAN_DEVICE_PATH *Vlan; + + Vlan = DevPath; + CatPrint (Str, L"Vlan(%d)", (UINTN) Vlan->VlanId); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathHardDrive ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + HARDDRIVE_DEVICE_PATH *Hd; + + Hd = DevPath; + switch (Hd->SignatureType) { + case SIGNATURE_TYPE_MBR: + CatPrint ( + Str, + L"HD(Part%d,Sig%08x)", + (UINTN) Hd->PartitionNumber, + (UINTN) *((UINT32 *) (&(Hd->Signature[0]))) + ); + break; + + case SIGNATURE_TYPE_GUID: + CatPrint ( + Str, + L"HD(Part%d,Sig%g)", + (UINTN) Hd->PartitionNumber, + (EFI_GUID *) &(Hd->Signature[0]) + ); + break; + + default: + CatPrint ( + Str, + L"HD(Part%d,MBRType=%02x,SigType=%02x)", + (UINTN) Hd->PartitionNumber, + (UINTN) Hd->MBRType, + (UINTN) Hd->SignatureType + ); + break; + } +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathCDROM ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CDROM_DEVICE_PATH *Cd; + + Cd = DevPath; + CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathFilePath ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + FILEPATH_DEVICE_PATH *Fp; + + Fp = DevPath; + CatPrint (Str, L"%s", Fp->PathName); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathMediaProtocol ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEDIA_PROTOCOL_DEVICE_PATH *MediaProt; + + MediaProt = DevPath; + CatPrint (Str, L"Media(%g)", &MediaProt->Protocol); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathFvFilePath ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath; + + FvFilePath = DevPath; + CatPrint (Str, L"%g", &FvFilePath->FvFileName); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathRelativeOffsetRange ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; + + Offset = DevPath; + CatPrint ( + Str, + L"Offset(%lx,%lx)", + Offset->StartingOffset, + Offset->EndingOffset + ); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathBssBss ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + BBS_BBS_DEVICE_PATH *Bbs; + CHAR16 *Type; + + Bbs = DevPath; + switch (Bbs->DeviceType) { + case BBS_TYPE_FLOPPY: + Type = L"Floppy"; + break; + + case BBS_TYPE_HARDDRIVE: + Type = L"Harddrive"; + break; + + case BBS_TYPE_CDROM: + Type = L"CDROM"; + break; + + case BBS_TYPE_PCMCIA: + Type = L"PCMCIA"; + break; + + case BBS_TYPE_USB: + Type = L"Usb"; + break; + + case BBS_TYPE_EMBEDDED_NETWORK: + Type = L"Net"; + break; + + case BBS_TYPE_BEV: + Type = L"BEV"; + break; + + default: + Type = L"?"; + break; + } + CatPrint (Str, L"Legacy-%s", Type); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathEndInstance ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CatPrint (Str, L","); +} + +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathNodeUnknown ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CatPrint (Str, L"?"); +} +/** + Convert Device Path to a Unicode string for printing. + + @param[in, out] Str The buffer holding the output string. + This buffer contains the length of the string and + the maixmum length reserved for the string buffer. + @param[in] DevPath The device path. + +**/ +VOID +DevPathFvPath ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEDIA_FW_VOL_DEVICE_PATH *FvPath; + + FvPath = DevPath; + CatPrint (Str, L"Fv(%g)", &FvPath->FvName); +} + +DEVICE_PATH_STRING_TABLE DevPathTable[] = { + { + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + DevPathPci + }, + { + HARDWARE_DEVICE_PATH, + HW_PCCARD_DP, + DevPathPccard + }, + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + DevPathMemMap + }, + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + DevPathVendor + }, + { + HARDWARE_DEVICE_PATH, + HW_CONTROLLER_DP, + DevPathController + }, + { + ACPI_DEVICE_PATH, + ACPI_DP, + DevPathAcpi + }, + { + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + DevPathExtendedAcpi + }, + { + ACPI_DEVICE_PATH, + ACPI_ADR_DP, + DevPathAdrAcpi + }, + { + MESSAGING_DEVICE_PATH, + MSG_ATAPI_DP, + DevPathAtapi + }, + { + MESSAGING_DEVICE_PATH, + MSG_SCSI_DP, + DevPathScsi + }, + { + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNEL_DP, + DevPathFibre + }, + { + MESSAGING_DEVICE_PATH, + MSG_1394_DP, + DevPath1394 + }, + { + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + DevPathUsb + }, + { + MESSAGING_DEVICE_PATH, + MSG_USB_WWID_DP, + DevPathUsbWWID + }, + { + MESSAGING_DEVICE_PATH, + MSG_DEVICE_LOGICAL_UNIT_DP, + DevPathLogicalUnit + }, + { + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + DevPathUsbClass + }, + { + MESSAGING_DEVICE_PATH, + MSG_SATA_DP, + DevPathSata + }, + { + MESSAGING_DEVICE_PATH, + MSG_I2O_DP, + DevPathI2O + }, + { + MESSAGING_DEVICE_PATH, + MSG_MAC_ADDR_DP, + DevPathMacAddr + }, + { + MESSAGING_DEVICE_PATH, + MSG_IPv4_DP, + DevPathIPv4 + }, + { + MESSAGING_DEVICE_PATH, + MSG_IPv6_DP, + DevPathIPv6 + }, + { + MESSAGING_DEVICE_PATH, + MSG_INFINIBAND_DP, + DevPathInfiniBand + }, + { + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + DevPathUart + }, + { + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + DevPathVendor + }, + { + MESSAGING_DEVICE_PATH, + MSG_ISCSI_DP, + DevPathiSCSI + }, + { + MESSAGING_DEVICE_PATH, + MSG_VLAN_DP, + DevPathVlan + }, + { + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP, + DevPathHardDrive + }, + { + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP, + DevPathCDROM + }, + { + MEDIA_DEVICE_PATH, + MEDIA_VENDOR_DP, + DevPathVendor + }, + { + MEDIA_DEVICE_PATH, + MEDIA_FILEPATH_DP, + DevPathFilePath + }, + { + MEDIA_DEVICE_PATH, + MEDIA_PROTOCOL_DP, + DevPathMediaProtocol + }, + { + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + DevPathFvPath, + }, + { + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_FILE_DP, + DevPathFvFilePath + }, + { + MEDIA_DEVICE_PATH, + MEDIA_RELATIVE_OFFSET_RANGE_DP, + DevPathRelativeOffsetRange, + }, + { + BBS_DEVICE_PATH, + BBS_BBS_DP, + DevPathBssBss + }, + { + END_DEVICE_PATH_TYPE, + END_INSTANCE_DEVICE_PATH_SUBTYPE, + DevPathEndInstance + }, + { + 0, + 0, + NULL + } +}; + + +/** + This function converts an input device structure to a Unicode string. + + @param[in] DevPath A pointer to the device path structure. + + @return A new allocated Unicode string that represents the device path. + +**/ +CHAR16 * +EFIAPI +DevicePathToStr ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + POOL_PRINT Str; + EFI_DEVICE_PATH_PROTOCOL *DevPathNode; + VOID (*DumpNode) (POOL_PRINT *, VOID *); + + UINTN Index; + UINTN NewSize; + + EFI_STATUS Status; + CHAR16 *ToText; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; + + ZeroMem (&Str, sizeof (Str)); + + if (DevPath == NULL) { + goto Done; + } + + Status = gBS->LocateProtocol ( + &gEfiDevicePathToTextProtocolGuid, + NULL, + (VOID **) &DevPathToText + ); + if (!EFI_ERROR (Status)) { + ToText = DevPathToText->ConvertDevicePathToText ( + DevPath, + FALSE, + TRUE + ); + ASSERT (ToText != NULL); + return ToText; + } + + // + // Process each device path node + // + DevPathNode = DevPath; + while (!IsDevicePathEnd (DevPathNode)) { + // + // Find the handler to dump this device path node + // + DumpNode = NULL; + for (Index = 0; DevPathTable[Index].Function != NULL; Index += 1) { + + if (DevicePathType (DevPathNode) == DevPathTable[Index].Type && + DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType + ) { + DumpNode = DevPathTable[Index].Function; + break; + } + } + // + // If not found, use a generic function + // + if (!DumpNode) { + DumpNode = DevPathNodeUnknown; + } + // + // Put a path seperator in if needed + // + if ((Str.Len != 0) && (DumpNode != DevPathEndInstance)) { + CatPrint (&Str, L"/"); + } + // + // Print this node of the device path + // + DumpNode (&Str, DevPathNode); + + // + // Next device path node + // + DevPathNode = NextDevicePathNode (DevPathNode); + } + +Done: + NewSize = (Str.Len + 1) * sizeof (CHAR16); + Str.Str = ReallocatePool (NewSize, NewSize, Str.Str); + ASSERT (Str.Str != NULL); + Str.Str[Str.Len] = 0; + return Str.Str; +} + diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf index b0254da30e..a6a207efe6 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf @@ -1,7 +1,7 @@ ## @file # Component name for SecureBoot configuration module. # -# Copyright (c) 2011, Intel Corporation. All rights reserved.
+# Copyright (c) 2011 - 2012, 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 @@ -27,6 +27,9 @@ [Sources] SecureBootConfigDriver.c SecureBootConfigImpl.c + SecureBootConfigFileExplorer.c + SecureBootConfigDevicePath.c + SecureBootConfigMisc.c SecureBootConfigImpl.h SecureBootConfig.vfr SecureBootConfigStrings.uni @@ -36,10 +39,12 @@ MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec SecurityPkg/SecurityPkg.dec + CryptoPkg/CryptoPkg.dec [LibraryClasses] BaseLib BaseMemoryLib + BaseCryptLib MemoryAllocationLib UefiLib UefiBootServicesTableLib @@ -48,15 +53,46 @@ UefiHiiServicesLib DebugLib HiiLib + PlatformSecureLib [Guids] gEfiIfrTianoGuid + gEfiCustomModeEnableGuid gEfiSecureBootEnableDisableGuid gSecureBootConfigFormSetGuid + gEfiCertRsa2048Guid ## CONSUMES + gEfiCertX509Guid ## CONSUMES + gEfiCertSha1Guid ## CONSUMES + gEfiCertSha256Guid ## CONSUMES + gEfiCertTypeRsa2048Sha256Guid ## CONSUMES + gEfiImageSecurityDatabaseGuid ## CONSUMES + gEfiFileSystemVolumeLabelInfoIdGuid ## CONSUMES + gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid + gEfiVT100PlusGuid ## CONSUMES ## GUID (The type of terminal) + gEfiVT100Guid ## CONSUMES ## GUID (The type of terminal) + ## CONSUMES ## GUID HOB (The hob holding memory type information) + gEfiVTUTF8Guid ## CONSUMES ## GUID (The type of terminal) + ## SOMETIMES_CONSUMES ## Variable:L"BootXX" (Boot option variable) + ## CONSUMES ## Variable:L"Timeout" (The time out value in second of showing progress bar) + ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array) + ## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" (The driver order list) + ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device) + ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device) + ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device) + gEfiFileInfoGuid ## CONSUMES ## GUID + gEfiPcAnsiGuid ## CONSUMES ## GUID (The type of terminal) + gEfiUartDevicePathGuid ## CONSUMES ## GUID (Identify the device path for UARD device) + gEfiSasDevicePathGuid ## CONSUMES ## GUID (Identify the device path for SAS device) [Protocols] gEfiHiiConfigAccessProtocolGuid ## PRODUCES gEfiHiiConfigRoutingProtocolGuid ## CONSUMES + gEfiSimpleFileSystemProtocolGuid ## PROTOCOL CONSUMES + gEfiLoadFileProtocolGuid ## PROTOCOL CONSUMES + gEfiBlockIoProtocolGuid ## PROTOCOL CONSUMES + gEfiDevicePathProtocolGuid ## PROTOCOL CONSUMES + gEfiDevicePathToTextProtocolGuid + gEfiDebugPortProtocolGuid [Depex] gEfiHiiConfigRoutingProtocolGuid AND diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigFileExplorer.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigFileExplorer.c new file mode 100644 index 0000000000..deff87bcbd --- /dev/null +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigFileExplorer.c @@ -0,0 +1,1227 @@ +/** @file + Internal file explorer functions for SecureBoot configuration module. + +Copyright (c) 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SecureBootConfigImpl.h" + +/// +/// File system selection menu +/// +SECUREBOOT_MENU_OPTION FsOptionMenu = { + SECUREBOOT_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Files and sub-directories in current directory menu +/// +SECUREBOOT_MENU_OPTION DirectoryMenu = { + SECUREBOOT_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +VOID *mStartOpCodeHandle = NULL; +VOID *mEndOpCodeHandle = NULL; +EFI_IFR_GUID_LABEL *mStartLabel = NULL; +EFI_IFR_GUID_LABEL *mEndLabel = NULL; + +/** + Duplicate a string. + + @param[in] Src The source string. + + @return A new string which is duplicated copy of the source, + or NULL if there is not enough memory. + +**/ +CHAR16 * +StrDuplicate ( + IN CHAR16 *Src + ) +{ + CHAR16 *Dest; + UINTN Size; + + Size = StrSize (Src); + Dest = AllocateZeroPool (Size); + ASSERT (Dest != NULL); + if (Dest != NULL) { + CopyMem (Dest, Src, Size); + } + + return Dest; +} + +/** + Helper function called as part of the code needed to allocate + the proper sized buffer for various EFI interfaces. + + @param[in, out] Status Current status + @param[in, out] Buffer Current allocated buffer, or NULL + @param[in] BufferSize Current buffer size needed + + @retval TRUE If the buffer was reallocated and the caller + should try the API again. + @retval FALSE The caller should not call this function again. + +**/ +BOOLEAN +GrowBuffer ( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +{ + BOOLEAN TryAgain; + + // + // If this is an initial request, buffer will be null with a new buffer size + // + if ((*Buffer == NULL) && (BufferSize != 0)) { + *Status = EFI_BUFFER_TOO_SMALL; + } + // + // If the status code is "buffer too small", resize the buffer + // + TryAgain = FALSE; + if (*Status == EFI_BUFFER_TOO_SMALL) { + + if (*Buffer != NULL) { + FreePool (*Buffer); + } + + *Buffer = AllocateZeroPool (BufferSize); + + if (*Buffer != NULL) { + TryAgain = TRUE; + } else { + *Status = EFI_OUT_OF_RESOURCES; + } + } + // + // If there's an error, free the buffer + // + if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) { + FreePool (*Buffer); + *Buffer = NULL; + } + + return TryAgain; +} + +/** + Append file name to existing file name, and allocate a new buffer + to hold the appended result. + + @param[in] Str1 The existing file name + @param[in] Str2 The file name to be appended + + @return A new string with appended result. + +**/ +CHAR16 * +AppendFileName ( + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ) +{ + UINTN Size1; + UINTN Size2; + CHAR16 *Str; + CHAR16 *TmpStr; + CHAR16 *Ptr; + CHAR16 *LastSlash; + + Size1 = StrSize (Str1); + Size2 = StrSize (Str2); + Str = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); + ASSERT (Str != NULL); + + TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); + ASSERT (TmpStr != NULL); + + StrCat (Str, Str1); + if (!((*Str == '\\') && (*(Str + 1) == 0))) { + StrCat (Str, L"\\"); + } + + StrCat (Str, Str2); + + Ptr = Str; + LastSlash = Str; + while (*Ptr != 0) { + if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') { + // + // Convert "\Name\..\" to "\" + // DO NOT convert the .. if it is at the end of the string. This will + // break the .. behavior in changing directories. + // + + // + // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings + // that overlap. + // + StrCpy (TmpStr, Ptr + 3); + StrCpy (LastSlash, TmpStr); + Ptr = LastSlash; + } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') { + // + // Convert a "\.\" to a "\" + // + + // + // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings + // that overlap. + // + StrCpy (TmpStr, Ptr + 2); + StrCpy (Ptr, TmpStr); + Ptr = LastSlash; + } else if (*Ptr == '\\') { + LastSlash = Ptr; + } + + Ptr++; + } + + FreePool (TmpStr); + + return Str; +} + +/** + Create a SECUREBOOT_MENU_ENTRY, and stores it in a buffer allocated from the pool. + + @return The new menu entry or NULL of error happens. + +**/ +SECUREBOOT_MENU_ENTRY * +CreateMenuEntry ( + VOID + ) +{ + SECUREBOOT_MENU_ENTRY *MenuEntry; + UINTN ContextSize; + + // + // Create new menu entry + // + MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY)); + if (MenuEntry == NULL) { + return NULL; + } + + ContextSize = sizeof (SECUREBOOT_FILE_CONTEXT); + MenuEntry->FileContext = AllocateZeroPool (ContextSize); + if (MenuEntry->FileContext == NULL) { + FreePool (MenuEntry); + return NULL; + } + + MenuEntry->Signature = SECUREBOOT_MENU_ENTRY_SIGNATURE; + + return MenuEntry; +} + +/** + Get Menu Entry from the Menu Entry List by MenuNumber. + + If MenuNumber is great or equal to the number of Menu + Entry in the list, then ASSERT. + + @param[in] MenuOption The Menu Entry List to read the menu entry. + @param[in] MenuNumber The index of Menu Entry. + + @return The Menu Entry. + +**/ +SECUREBOOT_MENU_ENTRY * +GetMenuEntry ( + IN SECUREBOOT_MENU_OPTION *MenuOption, + IN UINTN MenuNumber + ) +{ + SECUREBOOT_MENU_ENTRY *NewMenuEntry; + UINTN Index; + LIST_ENTRY *List; + + ASSERT (MenuNumber < MenuOption->MenuNumber); + + List = MenuOption->Head.ForwardLink; + for (Index = 0; Index < MenuNumber; Index++) { + List = List->ForwardLink; + } + + NewMenuEntry = CR (List, SECUREBOOT_MENU_ENTRY, Link, SECUREBOOT_MENU_ENTRY_SIGNATURE); + + return NewMenuEntry; +} + +/** + Create string tokens for a menu from its help strings and display strings. + + @param[in] HiiHandle Hii Handle of the package to be updated. + @param[in] MenuOption The Menu whose string tokens need to be created. + +**/ +VOID +CreateMenuStringToken ( + IN EFI_HII_HANDLE HiiHandle, + IN SECUREBOOT_MENU_OPTION *MenuOption + ) +{ + SECUREBOOT_MENU_ENTRY *NewMenuEntry; + UINTN Index; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = GetMenuEntry (MenuOption, Index); + + NewMenuEntry->DisplayStringToken = HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->DisplayString, + NULL + ); + + if (NewMenuEntry->HelpString == NULL) { + NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; + } else { + NewMenuEntry->HelpStringToken = HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->HelpString, + NULL + ); + } + } +} + +/** + Free up all resources allocated for a SECUREBOOT_MENU_ENTRY. + + @param[in, out] MenuEntry A pointer to SECUREBOOT_MENU_ENTRY. + +**/ +VOID +DestroyMenuEntry ( + IN OUT SECUREBOOT_MENU_ENTRY *MenuEntry + ) +{ + SECUREBOOT_FILE_CONTEXT *FileContext; + + + FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext; + + if (!FileContext->IsRoot) { + FreePool (FileContext->DevicePath); + } else { + if (FileContext->FHandle != NULL) { + FileContext->FHandle->Close (FileContext->FHandle); + } + } + + if (FileContext->FileName != NULL) { + FreePool (FileContext->FileName); + } + if (FileContext->Info != NULL) { + FreePool (FileContext->Info); + } + + FreePool (FileContext); + + FreePool (MenuEntry->DisplayString); + if (MenuEntry->HelpString != NULL) { + FreePool (MenuEntry->HelpString); + } + + FreePool (MenuEntry); +} + +/** + Free resources allocated in Allocate Rountine. + + @param[in, out] MenuOption Menu to be freed + +**/ +VOID +FreeMenu ( + IN OUT SECUREBOOT_MENU_OPTION *MenuOption + ) +{ + SECUREBOOT_MENU_ENTRY *MenuEntry; + while (!IsListEmpty (&MenuOption->Head)) { + MenuEntry = CR ( + MenuOption->Head.ForwardLink, + SECUREBOOT_MENU_ENTRY, + Link, + SECUREBOOT_MENU_ENTRY_SIGNATURE + ); + RemoveEntryList (&MenuEntry->Link); + DestroyMenuEntry (MenuEntry); + } + MenuOption->MenuNumber = 0; +} + +/** + This function gets the file information from an open file descriptor, and stores it + in a buffer allocated from pool. + + @param[in] FHand File Handle. + + @return A pointer to a buffer with file information or NULL is returned + +**/ +EFI_FILE_INFO * +FileInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; + + // + // Call the real function + // + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileInfoGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +/** + This function gets the file system information from an open file descriptor, + and stores it in a buffer allocated from pool. + + @param[in] FHand The file handle. + + @return A pointer to a buffer with file information. + @retval NULL is returned if failed to get Vaolume Label Info. + +**/ +EFI_FILE_SYSTEM_VOLUME_LABEL * +FileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_SYSTEM_VOLUME_LABEL *Buffer; + UINTN BufferSize; + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200; + + // + // Call the real function + // + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileSystemVolumeLabelInfoIdGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +/** + This function will open a file or directory referenced by DevicePath. + + This function opens a file with the open mode according to the file path. The + Attributes is valid only for EFI_FILE_MODE_CREATE. + + @param[in, out] FilePath On input, the device path to the file. + On output, the remaining device path. + @param[out] FileHandle Pointer to the file handle. + @param[in] OpenMode The mode to open the file with. + @param[in] Attributes The file's file attributes. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found on + the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +OpenFileByDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT EFI_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol; + EFI_FILE_PROTOCOL *Handle1; + EFI_FILE_PROTOCOL *Handle2; + EFI_HANDLE DeviceHandle; + + if ((FilePath == NULL || FileHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->LocateDevicePath ( + &gEfiSimpleFileSystemProtocolGuid, + FilePath, + &DeviceHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol( + DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID**)&EfiSimpleFileSystemProtocol, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1); + if (EFI_ERROR (Status)) { + FileHandle = NULL; + return Status; + } + + // + // go down directories one node at a time. + // + while (!IsDevicePathEnd (*FilePath)) { + // + // For file system access each node should be a file path component + // + if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH || + DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP + ) { + FileHandle = NULL; + return (EFI_INVALID_PARAMETER); + } + // + // Open this file path node + // + Handle2 = Handle1; + Handle1 = NULL; + + // + // Try to test opening an existing file + // + Status = Handle2->Open ( + Handle2, + &Handle1, + ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, + OpenMode &~EFI_FILE_MODE_CREATE, + 0 + ); + + // + // see if the error was that it needs to be created + // + if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) { + Status = Handle2->Open ( + Handle2, + &Handle1, + ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, + OpenMode, + Attributes + ); + } + // + // Close the last node + // + Handle2->Close (Handle2); + + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // Get the next node + // + *FilePath = NextDevicePathNode (*FilePath); + } + + // + // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also! + // + *FileHandle = (VOID*)Handle1; + return EFI_SUCCESS; +} + +/** + Function opens and returns a file handle to the root directory of a volume. + + @param[in] DeviceHandle A handle for a device + + @return A valid file handle or NULL if error happens. + +**/ +EFI_FILE_HANDLE +OpenRoot ( + IN EFI_HANDLE DeviceHandle + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_FILE_HANDLE File; + + File = NULL; + + // + // File the file system interface to the device + // + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID *) &Volume + ); + + // + // Open the root directory of the volume + // + if (!EFI_ERROR (Status)) { + Status = Volume->OpenVolume ( + Volume, + &File + ); + } + // + // Done + // + return EFI_ERROR (Status) ? NULL : File; +} + +/** + This function builds the FsOptionMenu list which records all + available file system in the system. They include all instances + of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM + and all type of legacy boot device. + + @retval EFI_SUCCESS Success find the file system + @retval EFI_OUT_OF_RESOURCES Can not create menu entry + +**/ +EFI_STATUS +FindFileSystem ( + VOID + ) +{ + UINTN NoBlkIoHandles; + UINTN NoSimpleFsHandles; + UINTN NoLoadFileHandles; + EFI_HANDLE *BlkIoHandle; + EFI_HANDLE *SimpleFsHandle; + UINT16 *VolumeLabel; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + UINTN Index; + EFI_STATUS Status; + SECUREBOOT_MENU_ENTRY *MenuEntry; + SECUREBOOT_FILE_CONTEXT *FileContext; + UINT16 *TempStr; + UINTN OptionNumber; + VOID *Buffer; + + BOOLEAN RemovableMedia; + + + NoSimpleFsHandles = 0; + NoLoadFileHandles = 0; + OptionNumber = 0; + InitializeListHead (&FsOptionMenu.Head); + + // + // Locate Handles that support BlockIo protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NoBlkIoHandles, + &BlkIoHandle + ); + if (!EFI_ERROR (Status)) { + + for (Index = 0; Index < NoBlkIoHandles; Index++) { + Status = gBS->HandleProtocol ( + BlkIoHandle[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + + if (EFI_ERROR (Status)) { + continue; + } + + // + // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media + // + if (BlkIo->Media->RemovableMedia) { + Buffer = AllocateZeroPool (BlkIo->Media->BlockSize); + if (NULL == Buffer) { + FreePool (BlkIoHandle); + return EFI_OUT_OF_RESOURCES; + } + + BlkIo->ReadBlocks ( + BlkIo, + BlkIo->Media->MediaId, + 0, + BlkIo->Media->BlockSize, + Buffer + ); + FreePool (Buffer); + } + } + FreePool (BlkIoHandle); + } + + // + // Locate Handles that support Simple File System protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NoSimpleFsHandles, + &SimpleFsHandle + ); + if (!EFI_ERROR (Status)) { + // + // Find all the instances of the File System prototocol + // + for (Index = 0; Index < NoSimpleFsHandles; Index++) { + Status = gBS->HandleProtocol ( + SimpleFsHandle[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (EFI_ERROR (Status)) { + // + // If no block IO exists assume it's NOT a removable media + // + RemovableMedia = FALSE; + } else { + // + // If block IO exists check to see if it's remobable media + // + RemovableMedia = BlkIo->Media->RemovableMedia; + } + + // + // Allocate pool for this instance. + // + MenuEntry = CreateMenuEntry (); + if (NULL == MenuEntry) { + FreePool (SimpleFsHandle); + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext; + + FileContext->Handle = SimpleFsHandle[Index]; + MenuEntry->OptionNumber = Index; + FileContext->FHandle = OpenRoot (FileContext->Handle); + if (FileContext->FHandle == NULL) { + DestroyMenuEntry (MenuEntry); + continue; + } + + MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle)); + FileContext->Info = FileSystemVolumeLabelInfo (FileContext->FHandle); + FileContext->FileName = StrDuplicate (L"\\"); + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + FileContext->IsDir = TRUE; + FileContext->IsRoot = TRUE; + FileContext->IsRemovableMedia = RemovableMedia; + FileContext->IsLoadFile = FALSE; + + // + // Get current file system's Volume Label + // + if (FileContext->Info == NULL) { + VolumeLabel = L"NO FILE SYSTEM INFO"; + } else { + if (FileContext->Info->VolumeLabel == NULL) { + VolumeLabel = L"NULL VOLUME LABEL"; + } else { + VolumeLabel = FileContext->Info->VolumeLabel; + if (*VolumeLabel == 0x0000) { + VolumeLabel = L"NO VOLUME LABEL"; + } + } + } + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"%s, [%s]", + VolumeLabel, + TempStr + ); + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + + if (NoSimpleFsHandles != 0) { + FreePool (SimpleFsHandle); + } + + // + // Remember how many file system options are here + // + FsOptionMenu.MenuNumber = OptionNumber; + return EFI_SUCCESS; +} + + +/** + Find files under the current directory. All files and sub-directories + in current directory will be stored in DirectoryMenu for future use. + + @param[in] MenuEntry The Menu Entry. + + @retval EFI_SUCCESS Get files from current dir successfully. + @return Other Can't get files from current dir. + +**/ +EFI_STATUS +FindFiles ( + IN SECUREBOOT_MENU_ENTRY *MenuEntry + ) +{ + EFI_FILE_HANDLE NewDir; + EFI_FILE_HANDLE Dir; + EFI_FILE_INFO *DirInfo; + UINTN BufferSize; + UINTN DirBufferSize; + SECUREBOOT_MENU_ENTRY *NewMenuEntry; + SECUREBOOT_FILE_CONTEXT *FileContext; + SECUREBOOT_FILE_CONTEXT *NewFileContext; + UINTN Pass; + EFI_STATUS Status; + UINTN OptionNumber; + + FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext; + Dir = FileContext->FHandle; + OptionNumber = 0; + // + // Open current directory to get files from it + // + Status = Dir->Open ( + Dir, + &NewDir, + FileContext->FileName, + EFI_FILE_READ_ONLY, + 0 + ); + if (!FileContext->IsRoot) { + Dir->Close (Dir); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + DirInfo = FileInfo (NewDir); + if (DirInfo == NULL) { + return EFI_NOT_FOUND; + } + + if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { + return EFI_INVALID_PARAMETER; + } + + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + + DirBufferSize = sizeof (EFI_FILE_INFO) + 1024; + DirInfo = AllocateZeroPool (DirBufferSize); + if (DirInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all files in current directory + // Pass 1 to get Directories + // Pass 2 to get files that are EFI images + // + for (Pass = 1; Pass <= 2; Pass++) { + NewDir->SetPosition (NewDir, 0); + for (;;) { + BufferSize = DirBufferSize; + Status = NewDir->Read (NewDir, &BufferSize, DirInfo); + if (EFI_ERROR (Status) || BufferSize == 0) { + break; + } + + if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) || + ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1) + ) { + // + // Pass 1 is for Directories + // Pass 2 is for file names + // + continue; + } + + NewMenuEntry = CreateMenuEntry (); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewFileContext = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext; + NewFileContext->Handle = FileContext->Handle; + NewFileContext->FileName = AppendFileName ( + FileContext->FileName, + DirInfo->FileName + ); + NewFileContext->FHandle = NewDir; + NewFileContext->DevicePath = FileDevicePath ( + NewFileContext->Handle, + NewFileContext->FileName + ); + NewMenuEntry->HelpString = NULL; + + NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY); + if (NewFileContext->IsDir) { + BufferSize = StrLen (DirInfo->FileName) * 2 + 6; + NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize); + + UnicodeSPrint ( + NewMenuEntry->DisplayString, + BufferSize, + L"<%s>", + DirInfo->FileName + ); + + } else { + NewMenuEntry->DisplayString = StrDuplicate (DirInfo->FileName); + } + + NewFileContext->IsRoot = FALSE; + NewFileContext->IsLoadFile = FALSE; + NewFileContext->IsRemovableMedia = FALSE; + + NewMenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link); + } + } + + DirectoryMenu.MenuNumber = OptionNumber; + FreePool (DirInfo); + return EFI_SUCCESS; +} + +/** + 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; +} + +/** + Update the File Explore page. + + @param[in] HiiHandle Hii Handle of the package to be updated. + @param[in] MenuOption The Menu whose string tokens need to be updated. + @param[in] FeCurrentState Current file explorer state. + +**/ +VOID +UpdateFileExplorePage ( + IN EFI_HII_HANDLE HiiHandle, + IN SECUREBOOT_MENU_OPTION *MenuOption, + IN FILE_EXPLORER_STATE FeCurrentState + ) +{ + UINTN Index; + SECUREBOOT_MENU_ENTRY *NewMenuEntry; + SECUREBOOT_FILE_CONTEXT *NewFileContext; + EFI_FORM_ID FormId; + EFI_FORM_ID FileFormId; + + if (FeCurrentState == FileExplorerStateEnrollPkFile) { + FormId = SECUREBOOT_ADD_PK_FILE_FORM_ID; + FileFormId = FORM_FILE_EXPLORER_ID_PK; + } else if (FeCurrentState == FileExplorerStateEnrollKekFile) { + FormId = FORMID_ENROLL_KEK_FORM; + FileFormId = FORM_FILE_EXPLORER_ID_KEK; + } else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDb) { + FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB; + FileFormId = FORM_FILE_EXPLORER_ID_DB; + } else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDbx) { + FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX; + FileFormId = FORM_FILE_EXPLORER_ID_DBX; + } else { + return; + } + + NewMenuEntry = NULL; + NewFileContext = NULL; + + RefreshUpdateData (); + mStartLabel->Number = FORM_FILE_EXPLORER_ID; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = GetMenuEntry (MenuOption, Index); + NewFileContext = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext; + + if (NewFileContext->IsDir) { + // + // Create Text opcode for directory. + // + HiiCreateActionOpCode ( + mStartOpCodeHandle, + (UINT16) (FILE_OPTION_OFFSET + Index), + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL), + EFI_IFR_FLAG_CALLBACK, + 0 + ); + } else { + + // + // Create Goto opcode for file. + // + HiiCreateGotoOpCode ( + mStartOpCodeHandle, + FormId, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL), + EFI_IFR_FLAG_CALLBACK, + (UINT16) (FILE_OPTION_OFFSET + Index) + ); + } + } + + HiiUpdateForm ( + HiiHandle, + &gSecureBootConfigFormSetGuid, + FileFormId, + mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID + mEndOpCodeHandle // LABEL_END + ); +} + +/** + Update the file explorer page with the refreshed file system. + + @param[in] PrivateData Module private data. + @param[in] KeyValue Key value to identify the type of data to expect. + + @retval TRUE Inform the caller to create a callback packet to exit file explorer. + @retval FALSE Indicate that there is no need to exit file explorer. + +**/ +BOOLEAN +UpdateFileExplorer ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData, + IN UINT16 KeyValue + ) +{ + UINT16 FileOptionMask; + SECUREBOOT_MENU_ENTRY *NewMenuEntry; + SECUREBOOT_FILE_CONTEXT *NewFileContext; + EFI_FORM_ID FormId; + BOOLEAN ExitFileExplorer; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; + + NewMenuEntry = NULL; + NewFileContext = NULL; + ExitFileExplorer = FALSE; + FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue); + + if (PrivateData->FeDisplayContext == FileExplorerDisplayUnknown) { + // + // First in, display file system. + // + FreeMenu (&FsOptionMenu); + FindFileSystem (); + + CreateMenuStringToken (PrivateData->HiiHandle, &FsOptionMenu); + UpdateFileExplorePage (PrivateData->HiiHandle, &FsOptionMenu, PrivateData->FeCurrentState); + + PrivateData->FeDisplayContext = FileExplorerDisplayFileSystem; + } else { + if (PrivateData->FeDisplayContext == FileExplorerDisplayFileSystem) { + NewMenuEntry = GetMenuEntry (&FsOptionMenu, FileOptionMask); + } else if (PrivateData->FeDisplayContext == FileExplorerDisplayDirectory) { + NewMenuEntry = GetMenuEntry (&DirectoryMenu, FileOptionMask); + } + + NewFileContext = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext; + + if (NewFileContext->IsDir ) { + PrivateData->FeDisplayContext = FileExplorerDisplayDirectory; + + RemoveEntryList (&NewMenuEntry->Link); + FreeMenu (&DirectoryMenu); + Status = FindFiles (NewMenuEntry); + if (EFI_ERROR (Status)) { + ExitFileExplorer = TRUE; + goto OnExit; + } + CreateMenuStringToken (PrivateData->HiiHandle, &DirectoryMenu); + DestroyMenuEntry (NewMenuEntry); + + UpdateFileExplorePage (PrivateData->HiiHandle, &DirectoryMenu, PrivateData->FeCurrentState); + + } else { + if (PrivateData->FeCurrentState == FileExplorerStateEnrollPkFile) { + FormId = SECUREBOOT_ADD_PK_FILE_FORM_ID; + } else if (PrivateData->FeCurrentState == FileExplorerStateEnrollKekFile) { + FormId = FORMID_ENROLL_KEK_FORM; + } else if (PrivateData->FeCurrentState == FileExplorerStateEnrollSignatureFileToDb) { + FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB; + } else if (PrivateData->FeCurrentState == FileExplorerStateEnrollSignatureFileToDbx) { + FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX; + } else { + return FALSE; + } + + PrivateData->MenuEntry = NewMenuEntry; + PrivateData->FileContext->FileName = NewFileContext->FileName; + + TmpDevicePath = NewFileContext->DevicePath; + OpenFileByDevicePath ( + &TmpDevicePath, + &PrivateData->FileContext->FHandle, + EFI_FILE_MODE_READ, + 0 + ); + + // + // Create Subtitle op-code for the display string of the option. + // + RefreshUpdateData (); + mStartLabel->Number = FormId; + + HiiCreateSubTitleOpCode ( + mStartOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + 0, + 0 + ); + + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSecureBootConfigFormSetGuid, + FormId, + mStartOpCodeHandle, // Label FormId + mEndOpCodeHandle // LABEL_END + ); + } + } + +OnExit: + return ExitFileExplorer; +} + +/** + 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 LabelId, + IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData + ) +{ + RefreshUpdateData (); + + // + // Remove all op-codes from dynamic page + // + mStartLabel->Number = LabelId; + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSecureBootConfigFormSetGuid, + LabelId, + mStartOpCodeHandle, // Label LabelId + mEndOpCodeHandle // LABEL_END + ); +} + diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index f846a72ca9..63dffd76bc 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -1,7 +1,7 @@ /** @file HII Config Access protocol implementation of SecureBoot configuration module. -Copyright (c) 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2011 - 2012, 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 @@ -14,10 +14,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "SecureBootConfigImpl.h" -CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION"; +CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION"; SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate = { - SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE, + SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE, { SecureBootExtractConfig, SecureBootRouteConfig, @@ -47,34 +47,2035 @@ HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath = { } }; + +// +// OID ASN.1 Value for Hash Algorithms +// +UINT8 mHashOidValue[] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5 + 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1 + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224 + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256 + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384 + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512 + }; + +HASH_TABLE mHash[] = { + { L"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, NULL, NULL, NULL, NULL }, + { L"SHA512", 64, &mHashOidValue[40], 9, NULL, NULL, NULL, NULL } +}; + + +// Variable Definitions +UINT32 mPeCoffHeaderOffset = 0; +WIN_CERTIFICATE *mCertificate = NULL; +IMAGE_TYPE mImageType; +UINT8 *mImageBase = NULL; +UINTN mImageSize = 0; +UINT8 mImageDigest[MAX_DIGEST_SIZE]; +UINTN mImageDigestSize; +EFI_GUID mCertType; +EFI_IMAGE_SECURITY_DATA_DIRECTORY *mSecDataDir = NULL; +EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader; + + +/** + Set Secure Boot option into variable space. + + @param[in] VarValue The option of Secure Boot. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval Others Other errors as indicated. + +**/ +EFI_STATUS +SaveSecureBootVariable ( + IN UINT8 VarValue + ) +{ + EFI_STATUS Status; + + Status = gRT->SetVariable ( + EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINT8), + &VarValue + ); + return Status; +} + +/** + 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; + + Variable = GetVariable (VariableName, VendorGuid); + if (Variable == NULL) { + return EFI_SUCCESS; + } + + Status = gRT->SetVariable ( + VariableName, + VendorGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, + NULL + ); + return Status; +} + +/** + Generate a PK signature list from the public key storing file (*.pbk). + + @param[in] PkKeyFile FileHandle of the public key storing file. + @param[out] PkCert Point to the data buffer to store the signature list. + + @return EFI_UNSUPPORTED Unsupported Key Length. + @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list. + +**/ +EFI_STATUS +CreatePkRsaSignatureList ( + IN EFI_FILE_HANDLE PkKeyFile, + OUT EFI_SIGNATURE_LIST **PkCert + ) +{ + EFI_STATUS Status; + UINTN KeyBlobSize; + VOID *KeyBlob; + CPL_KEY_INFO *KeyInfo; + EFI_SIGNATURE_DATA *PkCertData; + VOID *KeyBuffer; + UINTN KeyLenInBytes; + + PkCertData = NULL; + KeyBlob = NULL; + KeyBuffer = NULL; + Status = EFI_SUCCESS; + + // + // Get key from PK key file + // + Status = ReadFileContent (PkKeyFile, &KeyBlob, &KeyBlobSize, 0); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Can't Open the file for PK enrolling.\n")); + goto ON_EXIT; + } + + KeyInfo = (CPL_KEY_INFO *)KeyBlob; + if (KeyInfo->KeyLengthInBits/8 != WIN_CERT_UEFI_RSA2048_SIZE) { + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + } + + // + // Convert the Public key to fix octet string format represented in RSA PKCS#1. + // + KeyLenInBytes = KeyInfo->KeyLengthInBits / 8; + KeyBuffer = AllocateZeroPool(KeyLenInBytes); + if (KeyBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + Status = Int2OctStr ( + (UINTN*) ((UINTN)KeyBlob + sizeof(CPL_KEY_INFO)), + KeyLenInBytes / sizeof (UINTN), + (UINT8*)KeyBuffer, + KeyLenInBytes + ); + if (EFI_ERROR(Status)) { + goto ON_EXIT; + } + + // Allocate space for PK certificate list and initialize the list. + // Create PK database entry with SignatureHeaderSize equals 0. + // + *PkCert = (EFI_SIGNATURE_LIST*)AllocateZeroPool( + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + + WIN_CERT_UEFI_RSA2048_SIZE + ); + + if (*PkCert == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + (*PkCert)->SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + + sizeof(EFI_SIGNATURE_DATA) - 1 + + WIN_CERT_UEFI_RSA2048_SIZE; + (*PkCert)->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE; + (*PkCert)->SignatureHeaderSize = 0; + CopyGuid (&(*PkCert)->SignatureType, &gEfiCertRsa2048Guid); + + PkCertData = (EFI_SIGNATURE_DATA*)((UINTN)(*PkCert) + + sizeof(EFI_SIGNATURE_LIST) + + (*PkCert)->SignatureHeaderSize); + CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid); + // + // Fill the PK database with PKpub data from PKKeyFile. + // + CopyMem (&(PkCertData->SignatureData[0]), KeyBuffer, WIN_CERT_UEFI_RSA2048_SIZE); + +ON_EXIT: + + if (KeyBlob != NULL) { + FreePool (KeyBlob); + } + + if (EFI_ERROR(Status) && *PkCert != NULL) { + FreePool (*PkCert); + *PkCert = NULL; + } + + if (KeyBuffer != NULL) { + FreePool (KeyBuffer); + } + + return Status; +} + +/** + Generate the PK signature list from the X509 Certificate storing file (.cer) + + @param[in] X509File FileHandle of X509 Certificate storing file. + @param[out] PkCert Point to the data buffer to store the signature list. + + @return EFI_UNSUPPORTED Unsupported Key Length. + @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list. + +**/ +EFI_STATUS +CreatePkX509SignatureList ( + IN EFI_FILE_HANDLE X509File, + OUT EFI_SIGNATURE_LIST **PkCert + ) +{ + EFI_STATUS Status; + UINT8 *X509Data; + UINTN X509DataSize; + EFI_SIGNATURE_DATA *PkCertData; + + X509Data = NULL; + PkCertData = NULL; + X509DataSize = 0; + + Status = ReadFileContent (X509File, &X509Data, &X509DataSize, 0); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // + // Allocate space for PK certificate list and initialize it. + // Create PK database entry with SignatureHeaderSize equals 0. + // + *PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool ( + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + + X509DataSize + ); + if (*PkCert == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + (*PkCert)->SignatureListSize = (UINT32) (sizeof(EFI_SIGNATURE_LIST) + + sizeof(EFI_SIGNATURE_DATA) - 1 + + X509DataSize); + (*PkCert)->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); + (*PkCert)->SignatureHeaderSize = 0; + CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid); + PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert) + + sizeof(EFI_SIGNATURE_LIST) + + (*PkCert)->SignatureHeaderSize); + CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid); + // + // Fill the PK database with PKpub data from X509 certificate file. + // + CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize); + +ON_EXIT: + + if (X509Data != NULL) { + FreePool (X509Data); + } + + if (EFI_ERROR(Status) && *PkCert != NULL) { + FreePool (*PkCert); + *PkCert = NULL; + } + + return Status; +} + +/** + Enroll new PK into the System without original PK's authentication. + + The SignatureOwner GUID will be the same with PK's vendorguid. + + @param[in] PrivateData The module's private data. + + @retval EFI_SUCCESS New PK enrolled successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EnrollPlatformKey ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA* Private + ) +{ + EFI_STATUS Status; + UINT32 Attr; + UINTN DataSize; + EFI_SIGNATURE_LIST *PkCert; + UINT16* FilePostFix; + + if (Private->FileContext->FileName == NULL) { + return EFI_INVALID_PARAMETER; + } + + PkCert = NULL; + + // + // Parse the file's postfix. Only support *.pbk(RSA2048) and *.cer(X509) files. + // + FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4; + if (CompareMem (FilePostFix, L".pbk",4) && CompareMem (FilePostFix, L".cer",4)) { + DEBUG ((EFI_D_ERROR, "Don't support the file, only *.pbk or *.cer.\n is supported.")); + 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. + // + if (!CompareMem (FilePostFix, L".pbk",4)) { + Status = CreatePkRsaSignatureList ( + Private->FileContext->FHandle, + &PkCert + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + } else if (!CompareMem (FilePostFix, L".cer",4)) { + Status = CreatePkX509SignatureList ( + Private->FileContext->FHandle, + &PkCert + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + } + + // + // Set Platform Key variable. + // + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS; + DataSize = PkCert->SignatureListSize; + Status = gRT->SetVariable( + EFI_PLATFORM_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, + DataSize, + PkCert + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_OUT_OF_RESOURCES) { + DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n")); + } + goto ON_EXIT; + } + +ON_EXIT: + + if (PkCert != NULL) { + FreePool(PkCert); + } + + 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 = DeleteVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid); + + return Status; +} + +/** + Enroll a new KEK item from public key storing file (*.pbk). + + @param[in] PrivateData The module's private data. + + @retval EFI_SUCCESS New KEK enrolled successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Unsupported command. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EnrollRsa2048ToKek ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + UINT32 Attr; + UINTN DataSize; + EFI_SIGNATURE_LIST *KekSigList; + UINTN KeyBlobSize; + UINT8 *KeyBlob; + CPL_KEY_INFO *KeyInfo; + EFI_SIGNATURE_DATA *KEKSigData; + UINTN KekSigListSize; + UINT8 *KeyBuffer; + UINTN KeyLenInBytes; + + Attr = 0; + DataSize = 0; + KeyBuffer = NULL; + KeyBlobSize = 0; + KeyBlob = NULL; + KeyInfo = NULL; + KEKSigData = NULL; + KekSigList = NULL; + KekSigListSize = 0; + + // + // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type. + // First, We have to parse out public key data from the pbk key file. + // + Status = ReadFileContent ( + Private->FileContext->FHandle, + &KeyBlob, + &KeyBlobSize, + 0 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + KeyInfo = (CPL_KEY_INFO *) KeyBlob; + if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) { + DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n")); + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + } + + // + // Convert the Public key to fix octet string format represented in RSA PKCS#1. + // + KeyLenInBytes = KeyInfo->KeyLengthInBits / 8; + KeyBuffer = AllocateZeroPool (KeyLenInBytes); + if (KeyBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + Int2OctStr ( + (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)), + KeyLenInBytes / sizeof (UINTN), + KeyBuffer, + KeyLenInBytes + ); + CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes); + + // + // Form an new EFI_SIGNATURE_LIST. + // + KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + + sizeof(EFI_SIGNATURE_DATA) - 1 + + WIN_CERT_UEFI_RSA2048_SIZE; + + KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize); + if (KekSigList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + KekSigList->SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + + sizeof(EFI_SIGNATURE_DATA) - 1 + + WIN_CERT_UEFI_RSA2048_SIZE; + KekSigList->SignatureHeaderSize = 0; + KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE; + CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid); + + KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST)); + CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID); + CopyMem ( + KEKSigData->SignatureData, + KeyBlob + sizeof(CPL_KEY_INFO), + WIN_CERT_UEFI_RSA2048_SIZE + ); + + // + // Check if KEK entry has been already existed. + // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the + // new KEK to original variable. + // + Attr |= EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS; + DataSize = 0; + Status = gRT->GetVariable( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + NULL + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + Attr |= EFI_VARIABLE_APPEND_WRITE; + } else if (Status != EFI_NOT_FOUND) { + goto ON_EXIT; + } + + // + // Done. Now we have formed the correct KEKpub database item, just set it into variable storage, + // + Status = gRT->SetVariable( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, + KekSigListSize, + KekSigList + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + +ON_EXIT: + + CloseFile (Private->FileContext->FHandle); + Private->FileContext->FHandle = NULL; + Private->FileContext->FileName = NULL; + + if (Private->SignatureGUID != NULL) { + FreePool (Private->SignatureGUID); + Private->SignatureGUID = NULL; + } + + if (KeyBlob != NULL) { + FreePool (KeyBlob); + } + if (KeyBuffer != NULL) { + FreePool (KeyBuffer); + } + if (KekSigList != NULL) { + FreePool (KekSigList); + } + + return Status; +} + +/** + Enroll a new KEK item from X509 certificate file. + + @param[in] PrivateData The module's private data. + + @retval EFI_SUCCESS New X509 is enrolled successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Unsupported command. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EnrollX509ToKek ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + UINTN X509DataSize; + VOID *X509Data; + EFI_SIGNATURE_DATA *KEKSigData; + EFI_SIGNATURE_LIST *KekSigList; + UINTN DataSize; + UINTN KekSigListSize; + UINT32 Attr; + + X509Data = NULL; + X509DataSize = 0; + KekSigList = NULL; + KekSigListSize = 0; + DataSize = 0; + KEKSigData = NULL; + + Status = ReadFileContent ( + Private->FileContext->FHandle, + &X509Data, + &X509DataSize, + 0 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize; + KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize); + if (KekSigList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Fill Certificate Database parameters. + // + KekSigList->SignatureListSize = (UINT32) KekSigListSize; + KekSigList->SignatureHeaderSize = 0; + KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); + CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid); + + KEKSigData = (EFI_SIGNATURE_DATA*) ((UINT8*) KekSigList + sizeof (EFI_SIGNATURE_LIST)); + CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID); + CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize); + + // + // Check if KEK been already existed. + // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the + // new kek to original variable + // + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS; + + Status = gRT->GetVariable( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + NULL + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + Attr |= EFI_VARIABLE_APPEND_WRITE; + } else if (Status != EFI_NOT_FOUND) { + goto ON_EXIT; + } + + Status = gRT->SetVariable( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, + KekSigListSize, + KekSigList + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + +ON_EXIT: + + CloseFile (Private->FileContext->FHandle); + Private->FileContext->FileName = NULL; + Private->FileContext->FHandle = NULL; + + if (Private->SignatureGUID != NULL) { + FreePool (Private->SignatureGUID); + Private->SignatureGUID = NULL; + } + + if (KekSigList != NULL) { + FreePool (KekSigList); + } + + return Status; +} + +/** + Enroll new KEK into the System without PK's authentication. + The SignatureOwner GUID will be Private->SignatureGUID. + + @param[in] PrivateData The module's private data. + + @retval EFI_SUCCESS New KEK enrolled successful. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval others Fail to enroll KEK data. + +**/ +EFI_STATUS +EnrollKeyExchangeKey ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private + ) +{ + UINT16* FilePostFix; + + if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Parse the file's postfix. Supports .cer and .der file as X509 certificate, + // and .pbk as RSA public key file. + // + FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4; + if ((CompareMem (FilePostFix, L".cer",4) == 0) || (CompareMem (FilePostFix, L".der",4) == 0)) { + return EnrollX509ToKek (Private); + } else if (CompareMem (FilePostFix, L".pbk",4) == 0) { + return EnrollRsa2048ToKek (Private); + } else { + return EFI_INVALID_PARAMETER; + } +} + +/** + Enroll a new X509 certificate into Signature Database (DB or DBX) without + KEK's authentication. + + @param[in] PrivateData The module's private data. + @param[in] VariableName Variable name of signature database, must be + EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1. + + @retval EFI_SUCCESS New X509 is enrolled successfully. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +EnrollX509toSigDB ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, + IN CHAR16 *VariableName + ) +{ + EFI_STATUS Status; + UINTN X509DataSize; + VOID *X509Data; + EFI_SIGNATURE_LIST *SigDBCert; + EFI_SIGNATURE_DATA *SigDBCertData; + VOID *Data; + UINTN DataSize; + UINTN SigDBSize; + UINT32 Attr; + + X509DataSize = 0; + SigDBSize = 0; + DataSize = 0; + X509Data = NULL; + SigDBCert = NULL; + SigDBCertData = NULL; + Data = NULL; + + Status = ReadFileContent ( + Private->FileContext->FHandle, + &X509Data, + &X509DataSize, + 0 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize; + + Data = AllocateZeroPool (SigDBSize); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Fill Certificate Database parameters. + // + SigDBCert = (EFI_SIGNATURE_LIST*) Data; + SigDBCert->SignatureListSize = (UINT32) SigDBSize; + SigDBCert->SignatureHeaderSize = 0; + SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); + CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid); + + SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST)); + CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID); + CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize); + + // + // Check if signature database entry has been already existed. + // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the + // new signature data to original variable + // + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS; + + 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: + + CloseFile (Private->FileContext->FHandle); + Private->FileContext->FileName = NULL; + Private->FileContext->FHandle = NULL; + + if (Private->SignatureGUID != NULL) { + FreePool (Private->SignatureGUID); + Private->SignatureGUID = NULL; + } + + if (Data != NULL) { + FreePool (Data); + } + + if (X509Data != NULL) { + FreePool (X509Data); + } + + return Status; +} + +/** + Load PE/COFF image information into internal buffer and check its validity. + + @retval EFI_SUCCESS Successful + @retval EFI_UNSUPPORTED Invalid PE/COFF file + @retval EFI_ABORTED Serious error occurs, like file I/O error etc. + +**/ +EFI_STATUS +LoadPeImage ( + VOID + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_NT_HEADERS32 *NtHeader32; + EFI_IMAGE_NT_HEADERS64 *NtHeader64; + + NtHeader32 = NULL; + NtHeader64 = NULL; + // + // Read the Dos header + // + DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase); + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) + { + // + // DOS image header is present, + // So read the PE header after the DOS image header + // + mPeCoffHeaderOffset = DosHdr->e_lfanew; + } + else + { + mPeCoffHeaderOffset = 0; + } + + // + // Read PE header and check the signature validity and machine compatibility + // + NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset); + if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE) + { + return EFI_UNSUPPORTED; + } + + mNtHeader.Pe32 = NtHeader32; + + // + // Check the architecture field of PE header and get the Certificate Data Directory data + // Note the size of FileHeader field is constant for both IA32 and X64 arch + // + if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) + || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)) { + // + // IA-32 Architecture + // + mImageType = ImageType_IA32; + mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]); + } + else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) + || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)) { + // + // 64-bits Architecture + // + mImageType = ImageType_X64; + NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset); + mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]); + } else { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Calculate hash of Pe/Coff image based on the authenticode image hashing in + PE/COFF Specification 8.0 Appendix A + + @param[in] HashAlg Hash algorithm type. + + @retval TRUE Successfully hash image. + @retval FALSE Fail in hash image. + +**/ +BOOLEAN +HashPeImage ( + IN UINT32 HashAlg + ) +{ + BOOLEAN Status; + UINT16 Magic; + EFI_IMAGE_SECTION_HEADER *Section; + VOID *HashCtx; + UINTN CtxSize; + UINT8 *HashBase; + UINTN HashSize; + UINTN SumOfBytesHashed; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINTN Index; + UINTN Pos; + + HashCtx = NULL; + SectionHeader = NULL; + Status = FALSE; + + if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) { + return FALSE; + } + + // + // Initialize context of hash. + // + 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; + } + + CtxSize = mHash[HashAlg].GetContextSize(); + + HashCtx = AllocatePool (CtxSize); + ASSERT (HashCtx != NULL); + + // 1. Load the image header into memory. + + // 2. Initialize a SHA hash context. + Status = mHash[HashAlg].HashInit(HashCtx); + if (!Status) { + goto Done; + } + // + // Measuring PE/COFF Image Header; + // But CheckSum field and SECURITY data directory (certificate) are excluded + // + Magic = mNtHeader.Pe32->OptionalHeader.Magic; + // + // 3. Calculate the distance from the base of the image header to the image checksum address. + // 4. Hash the image header from its base to beginning of the image checksum. + // + HashBase = mImageBase; + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset. + // + HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase); + } else { + // + // Use PE32+ offset. + // + HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase); + } + + Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); + if (!Status) { + goto Done; + } + // + // 5. Skip over the image checksum (it occupies a single ULONG). + // 6. Get the address of the beginning of the Cert Directory. + // 7. Hash everything from the end of the checksum to the start of the Cert Directory. + // + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset. + // + HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - 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); + } + + Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); + if (!Status) { + goto Done; + } + // + // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.) + // 9. Hash everything from the end of the Cert Directory to the end of image header. + // + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; + HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - 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); + } + + Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); + if (!Status) { + goto Done; + } + // + // 10. Set the SUM_OF_BYTES_HASHED to the size of the header. + // + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset. + // + SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders; + } else { + // + // Use PE32+ offset + // + SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders; + } + + // + // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER + // structures in the image. The 'NumberOfSections' field of the image + // header indicates how big the table should be. Do not include any + // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections); + ASSERT (SectionHeader != NULL); + // + // 12. Using the 'PointerToRawData' in the referenced section headers as + // a key, arrange the elements in the table in ascending order. In other + // words, sort the section headers according to the disk-file offset of + // the section. + // + Section = (EFI_IMAGE_SECTION_HEADER *) ( + mImageBase + + mPeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader + ); + for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) { + Pos = Index; + while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) { + CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER)); + Pos--; + } + CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER)); + Section += 1; + } + + // + // 13. Walk through the sorted table, bring the corresponding section + // into memory, and hash the entire section (using the 'SizeOfRawData' + // field in the section header to determine the amount of data to hash). + // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED . + // 15. Repeat steps 13 and 14 for all the sections in the sorted table. + // + for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) { + Section = &SectionHeader[Index]; + if (Section->SizeOfRawData == 0) { + continue; + } + HashBase = mImageBase + Section->PointerToRawData; + HashSize = (UINTN) Section->SizeOfRawData; + + Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); + if (!Status) { + goto Done; + } + + SumOfBytesHashed += HashSize; + } + + // + // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra + // data in the file that needs to be added to the hash. This data begins + // at file offset SUM_OF_BYTES_HASHED and its length is: + // FileSize - (CertDirectory->Size) + // + if (mImageSize > SumOfBytesHashed) { + HashBase = mImageBase + SumOfBytesHashed; + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset. + // + HashSize = (UINTN)( + mImageSize - + mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - + SumOfBytesHashed); + } else { + // + // Use PE32+ offset. + // + HashSize = (UINTN)( + mImageSize - + mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - + SumOfBytesHashed); + } + + Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); + if (!Status) { + goto Done; + } + } + + Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest); + +Done: + if (HashCtx != NULL) { + FreePool (HashCtx); + } + if (SectionHeader != NULL) { + FreePool (SectionHeader); + } + return Status; +} + +/** + Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of + Pe/Coff image based on the authenticated image hashing in PE/COFF Specification + 8.0 Appendix A + + @retval EFI_UNSUPPORTED Hash algorithm is not supported. + @retval EFI_SUCCESS Hash successfully. + +**/ +EFI_STATUS +HashPeImageByType ( + VOID + ) +{ + UINT8 Index; + WIN_CERTIFICATE_EFI_PKCS *PkcsCertData; + + PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset); + + for (Index = 0; Index < HASHALG_MAX; Index++) { + // + // Check the Hash algorithm in PE/COFF Authenticode. + // According to PKCS#7 Definition: + // SignedData ::= SEQUENCE { + // version Version, + // digestAlgorithms DigestAlgorithmIdentifiers, + // contentInfo ContentInfo, + // .... } + // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing + // This field has the fixed offset (+32) in final Authenticode ASN.1 data. + // Fixed offset (+32) is calculated based on two bytes of length encoding. + // + if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) { + // + // Only support two bytes of Long Form of Length Encoding. + // + continue; + } + + // + if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) { + break; + } + } + + if (Index == HASHALG_MAX) { + return EFI_UNSUPPORTED; + } + + // + // HASH PE Image based on Hash algorithm in PE/COFF Authenticode. + // + if (!HashPeImage(Index)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Enroll a new executable's signature into Signature Database. + + @param[in] PrivateData The module's private data. + @param[in] VariableName Variable name of signature database, must be + EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1. + + @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; + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS; + + // + // Form the SigDB certificate list. + // Format the data item into EFI_SIGNATURE_LIST type. + // + // We need to parse executable's signature data from specified signed executable file. + // In current implementation, we simply trust the pass-in signed executable file. + // In reality, it's OS's responsibility to verify the signed executable file. + // + + // + // Read the whole file content + // + Status = ReadFileContent( + Private->FileContext->FHandle, + (VOID **) &mImageBase, + &mImageSize, + 0 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = LoadPeImage (); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + if (mSecDataDir->SizeOfCert == 0) { + if (!HashPeImage (HASHALG_SHA256)) { + Status = EFI_SECURITY_VIOLATION; + goto ON_EXIT; + } + } else { + + // + // Read the certificate data + // + mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset); + + if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) { + GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate; + if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + + if (!HashPeImage (HASHALG_SHA256)) { + Status = EFI_ABORTED; + goto ON_EXIT;; + } + + } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) { + + Status = HashPeImageByType (); + if (EFI_ERROR (Status)) { + goto ON_EXIT;; + } + } else { + Status = EFI_ABORTED; + goto ON_EXIT; + } + } + + // + // Create a new SigDB entry. + // + SigDBSize = sizeof(EFI_SIGNATURE_LIST) + + sizeof(EFI_SIGNATURE_DATA) - 1 + + (UINT32) mImageDigestSize; + + Data = (UINT8*) AllocateZeroPool (SigDBSize); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Adjust the Certificate Database parameters. + // + SigDBCert = (EFI_SIGNATURE_LIST*) Data; + SigDBCert->SignatureListSize = (UINT32) SigDBSize; + SigDBCert->SignatureHeaderSize = 0; + SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize; + CopyGuid (&SigDBCert->SignatureType, &mCertType); + + SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST)); + CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID); + CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize); + + // + // 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: + + CloseFile (Private->FileContext->FHandle); + Private->FileContext->FHandle = NULL; + Private->FileContext->FileName = NULL; + + if (Private->SignatureGUID != NULL) { + FreePool (Private->SignatureGUID); + Private->SignatureGUID = NULL; + } + + if (Data != NULL) { + FreePool (Data); + } + + if (mImageBase != NULL) { + FreePool (mImageBase); + mImageBase = NULL; + } + + return Status; +} + +/** + Enroll signature into DB/DBX without KEK's authentication. + The SignatureOwner GUID will be Private->SignatureGUID. + + @param[in] PrivateData The module's private data. + @param[in] VariableName Variable name of signature database, must be + EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1. + + @retval EFI_SUCCESS New signature enrolled successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval others Fail to enroll signature data. + +**/ +EFI_STATUS +EnrollSignatureDatabase ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, + IN CHAR16 *VariableName + ) +{ + UINT16* FilePostFix; + + if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Parse the file's postfix. + // + FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4; + if ((CompareMem (FilePostFix, L".cer",4) == 0) || (CompareMem (FilePostFix, L".der",4) == 0)) { + // + // Supports .cer and .der file as X509 certificate. + // + return EnrollX509toSigDB (Private, VariableName); + } + + return EnrollImageSignatureToSigDB (Private, VariableName); +} + +/** + List all signatures in specified signature database (e.g. KEK/DB/DBX) + by GUID in the page for user to select and delete as needed. + + @param[in] PrivateData Module's private data. + @param[in] VariableName The variable name of the vendor's signature database. + @param[in] VendorGuid A unique identifier for the vendor. + @param[in] LabelNumber Label number to insert opcodes. + @param[in] FormId Form ID of current page. + @param[in] QuestionIdBase Base question id of the signature list. + + @retval EFI_SUCCESS Success to update the signature list page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. + +**/ +EFI_STATUS +UpdateDeletePage ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT16 LabelNumber, + IN EFI_FORM_ID FormId, + IN EFI_QUESTION_ID QuestionIdBase + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINTN CertCount; + UINTN GuidIndex; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + UINTN DataSize; + UINT8 *Data; + EFI_SIGNATURE_LIST *CertList; + EFI_SIGNATURE_DATA *Cert; + UINT32 ItemDataSize; + CHAR16 *GuidStr; + EFI_STRING_ID GuidID; + EFI_STRING_ID Help; + + Data = NULL; + CertList = NULL; + Cert = NULL; + GuidStr = NULL; + StartOpCodeHandle = NULL; + EndOpCodeHandle = NULL; + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + if (StartOpCodeHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + if (EndOpCodeHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LabelNumber; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Read Variable. + // + DataSize = 0; + Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); + if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { + goto ON_EXIT; + } + + Data = (UINT8 *) AllocateZeroPool (DataSize); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + GuidStr = AllocateZeroPool (100); + if (GuidStr == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Enumerate all KEK pub data. + // + ItemDataSize = (UINT32) DataSize; + CertList = (EFI_SIGNATURE_LIST *) Data; + GuidIndex = 0; + + while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { + + if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) { + Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID); + } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { + Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID); + } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) { + Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID); + } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) { + Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID); + } else { + // + // The signature type is not supported in current implementation. + // + continue; + } + + CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; + for (Index = 0; Index < CertCount; Index++) { + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + + sizeof (EFI_SIGNATURE_LIST) + + CertList->SignatureHeaderSize + + Index * CertList->SignatureSize); + // + // Display GUID and help + // + GuidToString (&Cert->SignatureOwner, GuidStr, 100); + GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL); + HiiCreateCheckBoxOpCode ( + StartOpCodeHandle, + (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++), + 0, + 0, + GuidID, + Help, + EFI_IFR_FLAG_CALLBACK, + 0, + NULL + ); + } + + ItemDataSize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); + } + +ON_EXIT: + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSecureBootConfigFormSetGuid, + FormId, + StartOpCodeHandle, + EndOpCodeHandle + ); + + if (StartOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (StartOpCodeHandle); + } + + if (EndOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (EndOpCodeHandle); + } + + if (Data != NULL) { + FreePool (Data); + } + + if (GuidStr != NULL) { + FreePool (GuidStr); + } + + return EFI_SUCCESS; +} + /** - Save Secure Boot option to variable space. + Delete a KEK entry from KEK database. - @param[in] VarValue The option of Secure Boot. + @param[in] PrivateData Module's private data. + @param[in] QuestionId Question id of the KEK item to delete. - @retval EFI_SUCCESS The operation is finished successfully. - @retval Others Other errors as indicated. + @retval EFI_SUCCESS Delete kek item successfully. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. + +**/ +EFI_STATUS +DeleteKeyExchangeKey ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData, + IN EFI_QUESTION_ID QuestionId + ) +{ + EFI_STATUS Status; + UINTN DataSize; + UINT8 *Data; + UINT8 *OldData; + UINT32 Attr; + UINT32 Index; + EFI_SIGNATURE_LIST *CertList; + EFI_SIGNATURE_LIST *NewCertList; + EFI_SIGNATURE_DATA *Cert; + UINTN CertCount; + UINT32 Offset; + BOOLEAN IsKEKItemFound; + UINT32 KekDataSize; + UINTN DeleteKekIndex; + UINTN GuidIndex; + + Data = NULL; + OldData = NULL; + CertList = NULL; + Cert = NULL; + Attr = 0; + DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID; + + // + // Get original KEK variable. + // + DataSize = 0; + Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL); + if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) { + goto ON_EXIT; + } + + OldData = (UINT8*)AllocateZeroPool(DataSize); + if (OldData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData); + if (EFI_ERROR(Status)) { + goto ON_EXIT; + } + + // + // Allocate space for new variable. + // + Data = (UINT8*) AllocateZeroPool (DataSize); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Enumerate all KEK pub data and erasing the target item. + // + IsKEKItemFound = FALSE; + KekDataSize = (UINT32) DataSize; + CertList = (EFI_SIGNATURE_LIST *) OldData; + Offset = 0; + GuidIndex = 0; + while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) { + if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { + CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize)); + NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset); + Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); + CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; + for (Index = 0; Index < CertCount; Index++) { + if (GuidIndex == DeleteKekIndex ) { + // + // Find it! Skip it! + // + NewCertList->SignatureListSize -= CertList->SignatureSize; + IsKEKItemFound = TRUE; + } else { + // + // This item doesn't match. Copy it to the Data buffer. + // + CopyMem (Data + Offset, Cert, CertList->SignatureSize); + Offset += CertList->SignatureSize; + } + GuidIndex++; + Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize); + } + } else { + // + // This List doesn't match. Copy it to the Data buffer. + // + CopyMem (Data + Offset, CertList, CertList->SignatureListSize); + Offset += CertList->SignatureListSize; + } + + KekDataSize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize); + } + + if (!IsKEKItemFound) { + // + // Doesn't find the Kek Item! + // + Status = EFI_NOT_FOUND; + goto ON_EXIT; + } + + // + // Delete the Signature header if there is no signature in the list. + // + KekDataSize = Offset; + CertList = (EFI_SIGNATURE_LIST*) Data; + Offset = 0; + ZeroMem (OldData, KekDataSize); + while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) { + CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; + DEBUG ((DEBUG_ERROR, " CertCount = %x\n", CertCount)); + if (CertCount != 0) { + CopyMem (OldData + Offset, CertList, CertList->SignatureListSize); + Offset += CertList->SignatureListSize; + } + KekDataSize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); + } + + CertList = (EFI_SIGNATURE_LIST*) OldData; + DataSize = Offset; + + Status = gRT->SetVariable( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + Attr, + DataSize, + OldData + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status)); + goto ON_EXIT; + } + +ON_EXIT: + if (Data != NULL) { + FreePool(Data); + } + + if (OldData != NULL) { + FreePool(OldData); + } + + return UpdateDeletePage ( + PrivateData, + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + LABEL_KEK_DELETE, + FORMID_DELETE_KEK_FORM, + OPTION_DEL_KEK_QUESTION_ID + ); +} + +/** + Delete a signature entry from siganture database. + @param[in] PrivateData Module's private data. + @param[in] VariableName The variable name of the vendor's signature database. + @param[in] VendorGuid A unique identifier for the vendor. + @param[in] LabelNumber Label number to insert opcodes. + @param[in] FormId Form ID of current page. + @param[in] QuestionIdBase Base question id of the signature list. + @param[in] DeleteIndex Signature index to delete. + + @retval EFI_SUCCESS Delete siganture successfully. + @retval EFI_NOT_FOUND Can't find the signature item, + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. **/ EFI_STATUS -SaveSecureBootVariable ( - IN UINT8 VarValue +DeleteSignature ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT16 LabelNumber, + IN EFI_FORM_ID FormId, + IN EFI_QUESTION_ID QuestionIdBase, + IN UINTN DeleteIndex ) { - EFI_STATUS Status; + 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; - Status = gRT->SetVariable ( - EFI_SECURE_BOOT_ENABLE_NAME, - &gEfiSecureBootEnableDisableGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, - sizeof (UINT8), - &VarValue - ); + Data = NULL; + OldData = NULL; + CertList = NULL; + Cert = NULL; + Attr = 0; + + // + // Get original signature list data. + // + DataSize = 0; + Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL); + if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { + goto ON_EXIT; + } + + OldData = (UINT8 *) AllocateZeroPool (DataSize); + if (OldData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData); + if (EFI_ERROR(Status)) { + goto ON_EXIT; + } + + // + // Allocate space for new variable. + // + Data = (UINT8*) AllocateZeroPool (DataSize); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Enumerate all signature data and erasing the target item. + // + IsItemFound = FALSE; + ItemDataSize = (UINT32) DataSize; + CertList = (EFI_SIGNATURE_LIST *) OldData; + Offset = 0; + GuidIndex = 0; + while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { + if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) + ) { + // + // 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_ERROR, " 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); + } + + CertList = (EFI_SIGNATURE_LIST*) OldData; + DataSize = Offset; + + Status = gRT->SetVariable( + VariableName, + VendorGuid, + Attr, + DataSize, + OldData + ); if (EFI_ERROR (Status)) { - return Status; + DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status)); + goto ON_EXIT; } - gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); - return EFI_SUCCESS; + +ON_EXIT: + if (Data != NULL) { + FreePool(Data); + } + + if (OldData != NULL) { + FreePool(OldData); + } + + return UpdateDeletePage ( + PrivateData, + VariableName, + VendorGuid, + LabelNumber, + FormId, + QuestionIdBase + ); +} + +/** + This function extracts configuration from variable. + + @param[in, out] ConfigData Point to SecureBoot configuration private data. + +**/ +VOID +SecureBootExtractConfigFromVariable ( + IN OUT SECUREBOOT_CONFIGURATION *ConfigData + ) +{ + UINT8 *SecureBootEnable; + UINT8 *SetupMode; + UINT8 *SecureBootMode; + + SecureBootEnable = NULL; + SetupMode = NULL; + SecureBootMode = NULL; + + // + // Get the SecureBootEnable Variable + // + SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid); + + // + // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable + // Checkbox. + // + if (SecureBootEnable == NULL) { + ConfigData->HideSecureBoot = TRUE; + } else { + ConfigData->HideSecureBoot = FALSE; + ConfigData->SecureBootState = *SecureBootEnable; + } + // + // If it is Physical Presence User, set the PhysicalPresent to true. + // + if (UserPhysicalPresent()) { + ConfigData->PhysicalPresent = TRUE; + } else { + ConfigData->PhysicalPresent = FALSE; + } + + // + // If there is no PK then the Delete Pk button will be gray. + // + SetupMode = GetVariable (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid); + if (SetupMode == NULL || (*SetupMode) == 1) { + ConfigData->HasPk = FALSE; + } else { + ConfigData->HasPk = TRUE; + } + + // + // Get the SecureBootMode from CustomMode variable. + // + SecureBootMode = GetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid); + if (SecureBootMode == NULL) { + ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE; + } else { + ConfigData->SecureBootMode = *(SecureBootMode); + } + } /** @@ -116,16 +2117,15 @@ SecureBootExtractConfig ( UINTN BufferSize; UINTN Size; SECUREBOOT_CONFIGURATION Configuration; - EFI_STRING ConfigRequest; EFI_STRING ConfigRequestHdr; - UINT8 *SecureBootEnable; SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData; BOOLEAN AllocatedRequest; if (Progress == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; } + AllocatedRequest = FALSE; ConfigRequestHdr = NULL; ConfigRequest = NULL; @@ -139,30 +2139,16 @@ SecureBootExtractConfig ( return EFI_NOT_FOUND; } - - // - // Get the SecureBoot Variable - // - SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid); - // - // If the SecureBoot Variable doesn't exist, hide the SecureBoot Enable/Disable - // Checkbox. + // Get Configuration from Variable. // - if (SecureBootEnable == NULL) { - Configuration.HideSecureBoot = TRUE; - } else { - Configuration.HideSecureBoot = FALSE; - Configuration.SecureBootState = *SecureBootEnable; - } + SecureBootExtractConfigFromVariable (&Configuration); BufferSize = sizeof (SECUREBOOT_CONFIGURATION); ConfigRequest = Request; if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { // // Request is set to NULL or OFFSET is NULL, construct full request string. - // - // // Allocate and fill a buffer large enough to hold the template // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator @@ -231,12 +2217,6 @@ SecureBootRouteConfig ( OUT EFI_STRING *Progress ) { - EFI_STATUS Status; - UINTN BufferSize; - SECUREBOOT_CONFIGURATION SecureBootConfiguration; - UINT8 *SecureBootEnable; - - if (Configuration == NULL || Progress == NULL) { return EFI_INVALID_PARAMETER; } @@ -246,37 +2226,12 @@ SecureBootRouteConfig ( return EFI_NOT_FOUND; } - // - // Convert to buffer data by helper function ConfigToBlock() - // - BufferSize = sizeof (SECUREBOOT_CONFIGURATION); - Status = gHiiConfigRouting->ConfigToBlock ( - gHiiConfigRouting, - Configuration, - (UINT8 *) &SecureBootConfiguration, - &BufferSize, - Progress - ); - if (EFI_ERROR (Status)) { - return Status; - } - - SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid); - if (SecureBootEnable == NULL) { - return EFI_SUCCESS; - } - - if ((*SecureBootEnable) != SecureBootConfiguration.SecureBootState) { - // - // If the configure is changed, update the SecureBoot Variable. - // - SaveSecureBootVariable (SecureBootConfiguration.SecureBootState); - } + *Progress = Configuration + StrLen (Configuration); return EFI_SUCCESS; } /** - This function processes the results of changes in configuration. + This function is called to provide results data to the driver. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param[in] Action Specifies the type of action taken by the browser. @@ -308,24 +2263,271 @@ SecureBootCallback ( OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest ) { - BOOLEAN SecureBootEnable; + EFI_INPUT_KEY Key; + EFI_STATUS Status; + SECUREBOOT_CONFIG_PRIVATE_DATA *Private; + UINTN BufferSize; + SECUREBOOT_CONFIGURATION *IfrNvData; + UINT16 LabelId; if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } - if ((Action != EFI_BROWSER_ACTION_CHANGED) || (QuestionId != KEY_SECURE_BOOT_ENABLE)) { + if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING)) { return EFI_UNSUPPORTED; } + + Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); - if (NULL == GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid)) { - return EFI_SUCCESS; + // + // Retrieve uncommitted data from Browser + // + BufferSize = sizeof (SECUREBOOT_CONFIGURATION); + IfrNvData = AllocateZeroPool (BufferSize); + if (IfrNvData == NULL) { + return EFI_OUT_OF_RESOURCES; } - SecureBootEnable = Value->u8; - SaveSecureBootVariable (Value->u8); - return EFI_SUCCESS; + Status = EFI_SUCCESS; + + HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData); + + if (Action == EFI_BROWSER_ACTION_CHANGING) { + + switch (QuestionId) { + case KEY_SECURE_BOOT_ENABLE: + if (NULL != GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid)) { + if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Only Physical Presence User could disable secure boot!", + NULL + ); + Status = EFI_UNSUPPORTED; + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + } + 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: + // + // Clear Signature GUID. + // + ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid)); + if (Private->SignatureGUID == NULL) { + Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID)); + if (Private->SignatureGUID == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) { + LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB; + } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) { + LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX; + } else { + LabelId = FORMID_ENROLL_KEK_FORM; + } + + // + // Refresh selected file. + // + CleanUpPage (LabelId, Private); + break; + + case SECUREBOOT_ADD_PK_FILE_FORM_ID: + case FORMID_ENROLL_KEK_FORM: + case SECUREBOOT_ENROLL_SIGNATURE_TO_DB: + case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX: + 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 { + Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx; + } + + Private->FeDisplayContext = FileExplorerDisplayUnknown; + CleanUpPage (FORM_FILE_EXPLORER_ID, Private); + UpdateFileExplorer (Private, 0); + break; + + case KEY_SECURE_BOOT_DELETE_PK: + if (Value->u8) { + Status = DeletePlatformKey (); + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + } + break; + + case KEY_DELETE_KEK: + UpdateDeletePage ( + Private, + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + LABEL_KEK_DELETE, + FORMID_DELETE_KEK_FORM, + OPTION_DEL_KEK_QUESTION_ID + ); + break; + + case SECUREBOOT_DELETE_SIGNATURE_FROM_DB: + UpdateDeletePage ( + Private, + EFI_IMAGE_SECURITY_DATABASE, + &gEfiImageSecurityDatabaseGuid, + LABEL_DB_DELETE, + SECUREBOOT_DELETE_SIGNATURE_FROM_DB, + OPTION_DEL_DB_QUESTION_ID + ); + break; + + case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX: + UpdateDeletePage ( + Private, + EFI_IMAGE_SECURITY_DATABASE1, + &gEfiImageSecurityDatabaseGuid, + LABEL_DBX_DELETE, + SECUREBOOT_DELETE_SIGNATURE_FROM_DBX, + OPTION_DEL_DBX_QUESTION_ID + ); + + break; + + case KEY_VALUE_SAVE_AND_EXIT_KEK: + Status = EnrollKeyExchangeKey (Private); + break; + + case KEY_VALUE_SAVE_AND_EXIT_DB: + Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE); + break; + + case KEY_VALUE_SAVE_AND_EXIT_DBX: + Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1); + break; + + default: + if (QuestionId >= FILE_OPTION_OFFSET) { + UpdateFileExplorer (Private, QuestionId); + } else if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) && + (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) { + DeleteKeyExchangeKey (Private, QuestionId); + } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) && + (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) { + DeleteSignature ( + Private, + EFI_IMAGE_SECURITY_DATABASE, + &gEfiImageSecurityDatabaseGuid, + LABEL_DB_DELETE, + SECUREBOOT_DELETE_SIGNATURE_FROM_DB, + OPTION_DEL_DB_QUESTION_ID, + QuestionId - OPTION_DEL_DB_QUESTION_ID + ); + } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) && + (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) { + DeleteSignature ( + Private, + EFI_IMAGE_SECURITY_DATABASE1, + &gEfiImageSecurityDatabaseGuid, + LABEL_DBX_DELETE, + SECUREBOOT_DELETE_SIGNATURE_FROM_DBX, + OPTION_DEL_DBX_QUESTION_ID, + QuestionId - OPTION_DEL_DBX_QUESTION_ID + ); + } + break; + } + } else if (Action == EFI_BROWSER_ACTION_CHANGED) { + switch (QuestionId) { + case KEY_SECURE_BOOT_ENABLE: + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + break; + case KEY_VALUE_SAVE_AND_EXIT_PK: + Status = EnrollPlatformKey (Private); + if (EFI_ERROR (Status)) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"ERROR: The File Type is neither *.cer nor *.pbk!", + NULL + ); + } else { + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } + 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: + if (Private->FileContext->FHandle != NULL) { + CloseFile (Private->FileContext->FHandle); + Private->FileContext->FHandle = NULL; + Private->FileContext->FileName = NULL; + } + + if (Private->SignatureGUID != NULL) { + FreePool (Private->SignatureGUID); + Private->SignatureGUID = NULL; + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + break; + + case KEY_SECURE_BOOT_MODE: + if (NULL != GetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid)) { + Status = gRT->SetVariable ( + EFI_CUSTOM_MODE_NAME, + &gEfiCustomModeEnableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINT8), + &Value->u8 + ); + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + IfrNvData->SecureBootMode = Value->u8; + } + break; + + case KEY_SECURE_BOOT_KEK_GUID: + case KEY_SECURE_BOOT_SIGNATURE_GUID_DB: + case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX: + ASSERT (Private->SignatureGUID != NULL); + Status = StringToGuid ( + IfrNvData->SignatureGuid, + StrLen (IfrNvData->SignatureGuid), + Private->SignatureGUID + ); + if (EFI_ERROR (Status)) { + break; + } + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + break; + + case KEY_SECURE_BOOT_DELETE_PK: + if (Value->u8) { + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + } + break; + } + } + + if (!EFI_ERROR (Status)) { + BufferSize = sizeof (SECUREBOOT_CONFIGURATION); + HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8*) IfrNvData, NULL); + } + FreePool (IfrNvData); + + return EFI_SUCCESS; } /** @@ -333,7 +2535,7 @@ SecureBootCallback ( @param[in, out] PrivateData Points to SecureBoot configuration private data. - @retval EFI_SUCCESS HII Form is installed for this network device. + @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. @@ -346,7 +2548,6 @@ InstallSecureBootConfigForm ( EFI_STATUS Status; EFI_HII_HANDLE HiiHandle; EFI_HANDLE DriverHandle; - EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; DriverHandle = NULL; @@ -384,11 +2585,63 @@ InstallSecureBootConfigForm ( ConfigAccess, NULL ); - return EFI_OUT_OF_RESOURCES; } PrivateData->HiiHandle = HiiHandle; + + PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT)); + PrivateData->MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY)); + + if (PrivateData->FileContext == NULL || PrivateData->MenuEntry == 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 + // + mStartOpCodeHandle = HiiAllocateOpCodeHandle (); + if (mStartOpCodeHandle == NULL) { + UninstallSecureBootConfigForm (PrivateData); + return EFI_OUT_OF_RESOURCES; + } + + mEndOpCodeHandle = HiiAllocateOpCodeHandle (); + if (mEndOpCodeHandle == NULL) { + UninstallSecureBootConfigForm (PrivateData); + return EFI_OUT_OF_RESOURCES; + } + + // + // Create Hii Extend Label OpCode as the start opcode + // + mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + mStartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + + // + // Create Hii Extend Label OpCode as the end opcode + // + mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + mEndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + mEndLabel->Number = LABEL_END; + return EFI_SUCCESS; } @@ -426,5 +2679,28 @@ UninstallSecureBootConfigForm ( PrivateData->DriverHandle = NULL; } + if (PrivateData->SignatureGUID != NULL) { + 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); + } + + if (mEndOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mEndOpCodeHandle); + } } diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h index 603044d26e..7891503631 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h @@ -2,7 +2,7 @@ The header file of HII Config Access protocol implementation of SecureBoot configuration module. -Copyright (c) 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2011 - 2012, 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 @@ -20,6 +20,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -32,17 +38,158 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include - +#include +#include #include #include +#include +#include +#include #include "SecureBootConfigNvData.h" // // Tool generated IFR binary data and String package data // -extern UINT8 SecureBootConfigBin[]; -extern UINT8 SecureBootConfigDxeStrings[]; +extern UINT8 SecureBootConfigBin[]; +extern UINT8 SecureBootConfigDxeStrings[]; + +// +// 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 + +// +// SHA-1 digest size in bytes. +// +#define SHA1_DIGEST_SIZE 20 +// +// SHA-256 digest size in bytes +// +#define SHA256_DIGEST_SIZE 32 +// +// Set max digest size as SHA256 Output (32 bytes) by far +// +#define MAX_DIGEST_SIZE SHA256_DIGEST_SIZE + +#define WIN_CERT_UEFI_RSA2048_SIZE 256 + +// +// Support hash types +// +#define HASHALG_SHA1 0x00000000 +#define HASHALG_SHA224 0x00000001 +#define HASHALG_SHA256 0x00000002 +#define HASHALG_SHA384 0x00000003 +#define HASHALG_SHA512 0x00000004 +#define HASHALG_MAX 0x00000005 + + +#define SECUREBOOT_MENU_OPTION_SIGNATURE SIGNATURE_32 ('S', 'b', 'M', 'u') +#define SECUREBOOT_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('S', 'b', 'M', 'r') + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEVICE_PATH_WITH_DATA; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 NetworkProtocol; + UINT16 LoginOption; + UINT64 Lun; + UINT16 TargetPortalGroupTag; + CHAR16 TargetName[1]; +} ISCSI_DEVICE_PATH_WITH_NAME; + +typedef enum _FILE_EXPLORER_DISPLAY_CONTEXT { + FileExplorerDisplayFileSystem, + FileExplorerDisplayDirectory, + FileExplorerDisplayUnknown +} FILE_EXPLORER_DISPLAY_CONTEXT; + +typedef enum _FILE_EXPLORER_STATE { + FileExplorerStateInActive = 0, + FileExplorerStateEnrollPkFile, + FileExplorerStateEnrollKekFile, + FileExplorerStateEnrollSignatureFileToDb, + FileExplorerStateEnrollSignatureFileToDbx, + FileExplorerStateUnknown +} FILE_EXPLORER_STATE; + +typedef struct { + CHAR16 *Str; + UINTN Len; + UINTN Maxlen; +} POOL_PRINT; + +typedef +VOID +(*DEV_PATH_FUNCTION) ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ); + +typedef struct { + UINT8 Type; + UINT8 SubType; + DEV_PATH_FUNCTION Function; +} DEVICE_PATH_STRING_TABLE; + +typedef struct { + UINTN Signature; + LIST_ENTRY Head; + UINTN MenuNumber; +} SECUREBOOT_MENU_OPTION; + +extern SECUREBOOT_MENU_OPTION FsOptionMenu; +extern SECUREBOOT_MENU_OPTION DirectoryMenu; + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + UINTN OptionNumber; + UINT16 *DisplayString; + UINT16 *HelpString; + EFI_STRING_ID DisplayStringToken; + EFI_STRING_ID HelpStringToken; + VOID *FileContext; +} SECUREBOOT_MENU_ENTRY; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FILE_HANDLE FHandle; + UINT16 *FileName; + EFI_FILE_SYSTEM_VOLUME_LABEL *Info; + + BOOLEAN IsRoot; + BOOLEAN IsDir; + BOOLEAN IsRemovableMedia; + BOOLEAN IsLoadFile; + BOOLEAN IsBootLegacy; +} SECUREBOOT_FILE_CONTEXT; + + +// +// 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; /// /// HII specific Vendor Device Path definition. @@ -59,6 +206,13 @@ typedef struct { EFI_HII_HANDLE HiiHandle; EFI_HANDLE DriverHandle; + FILE_EXPLORER_STATE FeCurrentState; + FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext; + + SECUREBOOT_MENU_ENTRY *MenuEntry; + SECUREBOOT_FILE_CONTEXT *FileContext; + + EFI_GUID *SignatureGUID; } SECUREBOOT_CONFIG_PRIVATE_DATA; extern SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate; @@ -66,13 +220,123 @@ extern SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate; #define SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('S', 'E', 'C', 'B') #define SECUREBOOT_CONFIG_PRIVATE_FROM_THIS(a) CR (a, SECUREBOOT_CONFIG_PRIVATE_DATA, ConfigAccess, SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE) +// +// Cryptograhpic Key Information +// +#pragma pack (push, 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 (pop) + + +/** + Retrieves the size, in bytes, of the context buffer required for hash operations. + + @return The size, in bytes, of the context buffer required for hash operations. + +**/ +typedef +EFI_STATUS +(EFIAPI *HASH_GET_CONTEXT_SIZE)( + VOID + ); + +/** + Initializes user-supplied memory pointed by HashContext as hash context for + subsequent use. + + If HashContext is NULL, then ASSERT(). + + @param[in, out] HashContext Pointer to Context being initialized. + + @retval TRUE HASH context initialization succeeded. + @retval FALSE HASH context initialization failed. + +**/ +typedef +BOOLEAN +(EFIAPI *HASH_INIT)( + IN OUT VOID *HashContext + ); + + +/** + Performs digest on a data buffer of the specified length. This function can + be called multiple times to compute the digest of long or discontinuous data streams. + + If HashContext is NULL, then ASSERT(). + + @param[in, out] HashContext Pointer to the MD5 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataLength Length of Data buffer in bytes. + + @retval TRUE HASH data digest succeeded. + @retval FALSE Invalid HASH context. After HashFinal function has been called, the + HASH context cannot be reused. + +**/ +typedef +BOOLEAN +(EFIAPI *HASH_UPDATE)( + IN OUT VOID *HashContext, + IN CONST VOID *Data, + IN UINTN DataLength + ); + +/** + Completes hash computation and retrieves the digest value into the specified + memory. After this function has been called, the context cannot be used again. + + If HashContext is NULL, then ASSERT(). + If HashValue is NULL, then ASSERT(). + + @param[in, out] HashContext Pointer to the MD5 context + @param[out] HashValue Pointer to a buffer that receives the HASH digest + value (16 bytes). + + @retval TRUE HASH digest computation succeeded. + @retval FALSE HASH digest computation failed. + +**/ +typedef +BOOLEAN +(EFIAPI *HASH_FINAL)( + IN OUT VOID *HashContext, + OUT UINT8 *HashValue + ); + +// +// Hash Algorithm Table +// +typedef struct { + CHAR16 *Name; ///< Name for Hash Algorithm + UINTN DigestLength; ///< Digest Length + UINT8 *OidValue; ///< Hash Algorithm OID ASN.1 Value + UINTN OidLength; ///< Length of Hash OID Value + HASH_GET_CONTEXT_SIZE GetContextSize; ///< Pointer to Hash GetContentSize function + HASH_INIT HashInit; ///< Pointer to Hash Init function + HASH_UPDATE HashUpdate; ///< Pointer to Hash Update function + HASH_FINAL HashFinal; ///< Pointer to Hash Final function +} HASH_TABLE; + +typedef struct { + WIN_CERTIFICATE Hdr; + UINT8 CertData[1]; +} WIN_CERTIFICATE_EFI_PKCS; + /** This function publish the SecureBoot configuration Form. @param[in, out] PrivateData Points to SecureBoot configuration private data. - @retval EFI_SUCCESS HII Form is installed for this network device. + @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. @@ -82,6 +346,7 @@ InstallSecureBootConfigForm ( IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData ); + /** This function removes SecureBoot configuration Form. @@ -93,6 +358,7 @@ UninstallSecureBootConfigForm ( IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData ); + /** This function allows a caller to extract the current configuration for one or more named elements from the target driver. @@ -128,6 +394,7 @@ SecureBootExtractConfig ( OUT EFI_STRING *Results ); + /** This function processes the results of changes in configuration. @@ -154,6 +421,7 @@ SecureBootRouteConfig ( OUT EFI_STRING *Progress ); + /** This function processes the results of changes in configuration. @@ -187,4 +455,160 @@ SecureBootCallback ( OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest ); + +/** + This function converts an input device structure to a Unicode string. + + @param[in] DevPath A pointer to the device path structure. + + @return A new allocated Unicode string that represents the device path. + +**/ +CHAR16 * +EFIAPI +DevicePathToStr ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + + +/** + 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 LabelId, + IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData + ); + + +/** + Update the file explorer page with the refreshed file system. + + @param[in] PrivateData Module private data. + @param[in] KeyValue Key value to identify the type of data to expect. + + @retval TRUE Inform the caller to create a callback packet to exit file explorer. + @retval FALSE Indicate that there is no need to exit file explorer. + +**/ +BOOLEAN +UpdateFileExplorer ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData, + IN UINT16 KeyValue + ); + + +/** + Free resources allocated in Allocate Rountine. + + @param[in, out] MenuOption Menu to be freed + +**/ +VOID +FreeMenu ( + IN OUT SECUREBOOT_MENU_OPTION *MenuOption + ); + + +/** + Read file content into BufferPtr, the size of the allocate buffer + is *FileSize plus AddtionAllocateSize. + + @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] AddtionAllocateSize Addtion 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 +ReadFileContent ( + IN EFI_FILE_HANDLE FileHandle, + IN OUT VOID **BufferPtr, + OUT UINTN *FileSize, + IN UINTN AddtionAllocateSize + ); + + +/** + Close an open file handle. + + @param[in] FileHandle The file handle to close. + +**/ +VOID +CloseFile ( + IN EFI_FILE_HANDLE FileHandle + ); + + +/** + Converts 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 + ); + + +/** + Convert a String to Guid Value. + + @param[in] Str Specifies the String to be converted. + @param[in] StrLen Number of Unicode Characters of String (exclusive \0) + @param[out] Guid Return the result Guid value. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval EFI_NOT_FOUND Invalid string. + +**/ +EFI_STATUS +StringToGuid ( + IN CHAR16 *Str, + IN UINTN StrLen, + OUT EFI_GUID *Guid + ); + + +/** + 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 + ); + #endif diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigMisc.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigMisc.c new file mode 100644 index 0000000000..13c7c27387 --- /dev/null +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigMisc.c @@ -0,0 +1,334 @@ +/** @file + Helper functions for SecureBoot configuration module. + +Copyright (c) 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "SecureBootConfigImpl.h" + +/** + Read file content into BufferPtr, the size of the allocate buffer + is *FileSize plus AddtionAllocateSize. + + @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] AddtionAllocateSize Addtion 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 +ReadFileContent ( + IN EFI_FILE_HANDLE FileHandle, + IN OUT VOID **BufferPtr, + OUT UINTN *FileSize, + IN UINTN AddtionAllocateSize + ) + +{ + 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 + AddtionAllocateSize; + 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) { + FreePool (Buffer); + Buffer = NULL; + 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; +} + + + +/** + Convert a String to Guid Value. + + @param[in] Str Specifies the String to be converted. + @param[in] StrLen Number of Unicode Characters of String (exclusive \0) + @param[out] Guid Return the result Guid value. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval EFI_NOT_FOUND Invalid string. + +**/ +EFI_STATUS +StringToGuid ( + IN CHAR16 *Str, + IN UINTN StrLen, + OUT EFI_GUID *Guid + ) +{ + CHAR16 *PtrBuffer; + CHAR16 *PtrPosition; + UINT16 *Buffer; + UINTN Data; + UINTN Index; + UINT16 Digits[3]; + + Buffer = (CHAR16 *) AllocateZeroPool (sizeof (CHAR16) * (StrLen + 1)); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StrCpy (Buffer, Str); + + // + // Data1 + // + PtrBuffer = Buffer; + PtrPosition = PtrBuffer; + while (*PtrBuffer != L'\0') { + if (*PtrBuffer == L'-') { + break; + } + PtrBuffer++; + } + if (*PtrBuffer == L'\0') { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + + *PtrBuffer = L'\0'; + Data = StrHexToUintn (PtrPosition); + Guid->Data1 = (UINT32)Data; + + // + // Data2 + // + PtrBuffer++; + PtrPosition = PtrBuffer; + while (*PtrBuffer != L'\0') { + if (*PtrBuffer == L'-') { + break; + } + PtrBuffer++; + } + if (*PtrBuffer == L'\0') { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + *PtrBuffer = L'\0'; + Data = StrHexToUintn (PtrPosition); + Guid->Data2 = (UINT16)Data; + + // + // Data3 + // + PtrBuffer++; + PtrPosition = PtrBuffer; + while (*PtrBuffer != L'\0') { + if (*PtrBuffer == L'-') { + break; + } + PtrBuffer++; + } + if (*PtrBuffer == L'\0') { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + *PtrBuffer = L'\0'; + Data = StrHexToUintn (PtrPosition); + Guid->Data3 = (UINT16)Data; + + // + // Data4[0..1] + // + for ( Index = 0 ; Index < 2 ; Index++) { + PtrBuffer++; + if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + Digits[0] = *PtrBuffer; + PtrBuffer++; + Digits[1] = *PtrBuffer; + Digits[2] = L'\0'; + Data = StrHexToUintn (Digits); + Guid->Data4[Index] = (UINT8)Data; + } + + // + // skip the '-' + // + PtrBuffer++; + if ((*PtrBuffer != L'-' ) || ( *PtrBuffer == L'\0')) { + return EFI_NOT_FOUND; + } + + // + // Data4[2..7] + // + for ( ; Index < 8; Index++) { + PtrBuffer++; + if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) { + FreePool (Buffer); + return EFI_NOT_FOUND; + } + Digits[0] = *PtrBuffer; + PtrBuffer++; + Digits[1] = *PtrBuffer; + Digits[2] = L'\0'; + Data = StrHexToUintn (Digits); + Guid->Data4[Index] = (UINT8)Data; + } + + FreePool (Buffer); + + 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; +} diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h index 278066e87f..6015dd636d 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h @@ -1,7 +1,7 @@ /** @file Header file for NV data structure definition. -Copyright (c) 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2011 - 2012, 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 @@ -18,17 +18,101 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +// +// Used by VFR for form or button identification +// #define SECUREBOOT_CONFIGURATION_VARSTORE_ID 0x0001 -#define SECUREBOOT_CONFIGURATION_FORM_ID 0x0001 +#define SECUREBOOT_CONFIGURATION_FORM_ID 0x01 +#define FORMID_SECURE_BOOT_OPTION_FORM 0x02 +#define FORMID_SECURE_BOOT_PK_OPTION_FORM 0x03 +#define FORMID_SECURE_BOOT_KEK_OPTION_FORM 0x04 +#define FORMID_SECURE_BOOT_DB_OPTION_FORM 0x05 +#define FORMID_SECURE_BOOT_DBX_OPTION_FORM 0x06 +#define FORMID_ENROLL_PK_FORM 0x07 +#define SECUREBOOT_ADD_PK_FILE_FORM_ID 0x08 +#define FORMID_ENROLL_KEK_FORM 0x09 +#define FORMID_DELETE_KEK_FORM 0x0a +#define SECUREBOOT_ENROLL_SIGNATURE_TO_DB 0x0b +#define SECUREBOOT_DELETE_SIGNATURE_FROM_DB 0x0c +#define SECUREBOOT_ENROLL_SIGNATURE_TO_DBX 0x0d +#define SECUREBOOT_DELETE_SIGNATURE_FROM_DBX 0x0e +#define FORM_FILE_EXPLORER_ID 0x0f +#define FORM_FILE_EXPLORER_ID_PK 0x10 +#define FORM_FILE_EXPLORER_ID_KEK 0x11 +#define FORM_FILE_EXPLORER_ID_DB 0x12 +#define FORM_FILE_EXPLORER_ID_DBX 0x13 + +#define SECURE_BOOT_MODE_CUSTOM 0x01 +#define SECURE_BOOT_MODE_STANDARD 0x00 + +#define KEY_SECURE_BOOT_ENABLE 0x1000 +#define KEY_SECURE_BOOT_MODE 0x1001 +#define KEY_VALUE_SAVE_AND_EXIT_DB 0x1002 +#define KEY_VALUE_NO_SAVE_AND_EXIT_DB 0x1003 +#define KEY_VALUE_SAVE_AND_EXIT_PK 0x1004 +#define KEY_VALUE_NO_SAVE_AND_EXIT_PK 0x1005 +#define KEY_VALUE_SAVE_AND_EXIT_KEK 0x1008 +#define KEY_VALUE_NO_SAVE_AND_EXIT_KEK 0x1009 +#define KEY_VALUE_SAVE_AND_EXIT_DBX 0x100a +#define KEY_VALUE_NO_SAVE_AND_EXIT_DBX 0x100b + +#define KEY_SECURE_BOOT_OPTION 0x1100 +#define KEY_SECURE_BOOT_PK_OPTION 0x1101 +#define KEY_SECURE_BOOT_KEK_OPTION 0x1102 +#define KEY_SECURE_BOOT_DB_OPTION 0x1103 +#define KEY_SECURE_BOOT_DBX_OPTION 0x1104 +#define KEY_SECURE_BOOT_DELETE_PK 0x1105 +#define KEY_ENROLL_PK 0x1106 +#define KEY_ENROLL_KEK 0x1107 +#define KEY_DELETE_KEK 0x1108 +#define KEY_SECURE_BOOT_KEK_GUID 0x110a +#define KEY_SECURE_BOOT_SIGNATURE_GUID_DB 0x110b +#define KEY_SECURE_BOOT_SIGNATURE_GUID_DBX 0x110c + +#define LABEL_KEK_DELETE 0x1200 +#define LABEL_DB_DELETE 0x1201 +#define LABEL_DBX_DELETE 0x1202 +#define LABEL_END 0xffff + +#define SECURE_BOOT_MAX_ATTEMPTS_NUM 255 + +#define CONFIG_OPTION_OFFSET 0x2000 + +#define OPTION_CONFIG_QUESTION_ID 0x2000 +#define OPTION_CONFIG_RANGE 0x1000 + +// +// Question ID 0x2000 ~ 0x2FFF is for KEK +// +#define OPTION_DEL_KEK_QUESTION_ID 0x2000 +// +// Question ID 0x3000 ~ 0x3FFF is for DB +// +#define OPTION_DEL_DB_QUESTION_ID 0x3000 +// +// Question ID 0x4000 ~ 0x4FFF is for DBX +// +#define OPTION_DEL_DBX_QUESTION_ID 0x4000 + + +#define FILE_OPTION_OFFSET 0x8000 +#define FILE_OPTION_MASK 0x7FFF + +#define SECURE_BOOT_GUID_SIZE 36 +#define SECURE_BOOT_GUID_STORAGE_SIZE 37 + -#define KEY_SECURE_BOOT_ENABLE 0x5000 - // // Nv Data structure referenced by IFR // typedef struct { - BOOLEAN SecureBootState; - BOOLEAN HideSecureBoot; + BOOLEAN SecureBootState; //Secure Boot Disable/Enable; + BOOLEAN HideSecureBoot; //Hiden Attempt Secure Boot + CHAR16 SignatureGuid[SECURE_BOOT_GUID_STORAGE_SIZE]; + BOOLEAN PhysicalPresent; //If a Physical Present User; + UINT8 SecureBootMode; //Secure Boot Mode: Standard Or Custom + BOOLEAN DeletePk; + BOOLEAN HasPk; //If Pk is existed it is true; } SECUREBOOT_CONFIGURATION; #endif diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni index 99f728ead0cab465ce0195f57dfc2fde4ec4716d..ed4db131e9b0dd8547b4cf22e3915a25fee3abd1 100644 GIT binary patch literal 9518 zcmcIq+iu%N5S`Z+=syt7OIuWSP6XSMAj_@uB*-_#h-Dj+oXgKAJ!i)& zlG-JANvj|za_?u)&dkm%_3i7H{ERD+zvW7<$2l*c9M2=-4GvwXM1gQ&@u*NO! z1@1e%&5?hFx0$JZDd+Nl_e-R9k$Z=FiR_u0Y&kKd<7I2xb}E}@OpeRi_wvPzJCXOM zhab`JPv~h|ewF9A5@{?`+wu$EJHWEQxHoub4>R<^-*l`^lr&M!8l02%P5i_=$32se z_`Lv@S3p0I*9OxN7_QAc?@{9p?bz!S?Zz1M0?!3%aK>YxJV%Ww#%9?Uv{UA$NE02$ z9RmSJ?4S2g-bx$e^&ulYd4u1k93kBSg9$j~bBNpyr04{1ZNuw{bn$E> zpB!ipDd!zXZ5uU?P0u~NQCj)CfhYTAuN!#onlw|Cd*b;QW$dwMMoW-xVicn4BEN$k z*}i8+9w0^B%;R`N)M6cusI~S{mo4And4Lk4=1A?wQFI1vIbHUX_TB*xeMk_;Y-Mzs z_GN3y-!t$_$($I;=8AKT8bHsUHqe%3T!T4y-^jGHQl(m@ERW1g_RyNM+Qm$In9<10 zY6vV`sj@3Y^8i#6BU^bq$H=Q@*A(-!r542Cr9>Qpy)vvU3*+rWzNwRQ)P7~yRGaV` z=>?=eK?yA-XGOg!njf{t>h2t?8D5DlR^bp=Xb%4J@XW#pDAiULMj2^PU8QsmOVEW8 zG{Fejq>V4;E`I&97~>=$jFI|d_lPa%A@#_nQ+r>u>Q|T@?WykL^%TKjklYkkp0L^Q5d>+g5drnplgLSAIsa zkCoEhC(HviwoJwotoz(BKtFsRZ?xVqy4jR}3M4#>&`MMO8OD7KF6lG-B)=X`dLCqy z{sq07JR*N8gp)o6V}dCzm9IS`U)+_|ceQ?U8-6Hjl=SBw@ z4aDIsvocm1m09{|^att7#du0Fn5|UOQ~V6AzA=6_W0M#;_3zq8KuJqIGQMWdc$cnB zgwSmidN@bG$mptky^DN`6kXZQ{d9CMjRZWv0?>P7~8aUw&Eb8Q)SPsXRy7 zR8?F>URp2bo7a=yEaL3Goy8l&BzLduF0C;}p5M56aL=GbPoH2j^0Q)W>x%;a&vhuX z!$r2Fk63#IS!aAwEJI<`?1!;_Hgc;c9WElDjD!(oeH%t28hNU}%rWYrJHW0GW-N?O z`&kcTK1?oWVN7L==@|7mYat$9hm5hG^)Tila`}q2K-Pa=l`%K|sn6bNkiYQia?Yn~ zP&|L;0PgEL9C7&t5~8!^Pt=Q;aAMkGtz-nN*akds>md zlg1Njd9BA@j4@jh#+$}!x;FeClSYxnsQliJk6jmW7?qE&da-W)L}&f-x4LtE2<%)g zo>cz6gZ`IYVcr-K^84D{MBnOhts*=y=k`7LX8htZlTTQ2t^Wb(OZW)sX<({P)pR^2 zdbBeQ&&rjCs&>cj=XT7{vnr;T{Wq^0)+;EB5wj@c5QQv{jN#;?t0)Qf${hjC=r#&Hn