From ed47ae02744bee893531ef4f9072afd93e4f4efd Mon Sep 17 00:00:00 2001 From: tye1 Date: Sat, 31 Mar 2012 04:42:20 +0000 Subject: [PATCH] Update common authenticated variable (non PK/KEK/DB/DBX) support to comply with latest UEFI spec. Signed-off by: tye1 Reviewed-by: geekboy15a Reviewed-by: sfu5 Reviewed-by: gdong1 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13157 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Guid/AuthenticatedVariableFormat.h | 9 + SecurityPkg/SecurityPkg.dec | 9 +- .../RuntimeDxe/AuthService.c | 644 +++++++++++++++++- .../RuntimeDxe/AuthService.h | 23 +- .../RuntimeDxe/VariableRuntimeDxe.inf | 1 + .../RuntimeDxe/VariableSmm.inf | 1 + 6 files changed, 661 insertions(+), 26 deletions(-) diff --git a/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h b/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h index 7e543ee911..f18f4aa7eb 100644 --- a/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h +++ b/SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h @@ -49,6 +49,15 @@ extern EFI_GUID gEfiCustomModeEnableGuid; #define CUSTOM_SECURE_BOOT_MODE 1 #define STANDARD_SECURE_BOOT_MODE 0 +/// +/// "certdb" variable stores the signer's certificates for non PK/KEK/DB/DBX +/// variables with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set. +/// +/// +#define EFI_CERT_DB_NAME L"certdb" + +extern EFI_GUID gEfiCertDbGuid; + /// /// Alignment of variable name and data, according to the architecture: /// * For IA-32 and Intel(R) 64 architectures: 1. diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec index e5471778ee..38e3c25619 100644 --- a/SecurityPkg/SecurityPkg.dec +++ b/SecurityPkg/SecurityPkg.dec @@ -30,16 +30,19 @@ [Guids] ## Security package token space guid # Include/Guid/SecurityPkgTokenSpace.h - gEfiSecurityPkgTokenSpaceGuid = { 0xd3fb176, 0x9569, 0x4d51, { 0xa3, 0xef, 0x7d, 0x61, 0xc6, 0x4f, 0xea, 0xba }} + gEfiSecurityPkgTokenSpaceGuid = { 0xd3fb176, 0x9569, 0x4d51, { 0xa3, 0xef, 0x7d, 0x61, 0xc6, 0x4f, 0xea, 0xba }} ## Guid acted as the authenticated variable store header's signature, and to specify the variable list entries put in the EFI system table. # Include/Guid/AuthenticatedVariableFormat.h - gEfiAuthenticatedVariableGuid = { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } } + gEfiAuthenticatedVariableGuid = { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } } # Include/Guid/AuthenticatedVariableFormat.h - gEfiSecureBootEnableDisableGuid = { 0xf0a30bc7, 0xaf08, 0x4556, { 0x99, 0xc4, 0x0, 0x10, 0x9, 0xc9, 0x3a, 0x44 } } + 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/AuthenticatedVariableFormat.h + gEfiCertDbGuid = { 0xd9bee56e, 0x75dc, 0x49d9, { 0xb4, 0xd7, 0xb5, 0x34, 0x21, 0xf, 0x63, 0x7a } } ## 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 4036885570..12587af7b2 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c @@ -164,6 +164,7 @@ AutenticatedVariableServiceInitialize ( UINT8 SecureBootMode; UINT8 SecureBootEnable; UINT8 CustomMode; + UINT32 ListSize; // // Initialize hash context. @@ -388,6 +389,36 @@ AutenticatedVariableServiceInitialize ( DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME, CustomMode)); + // + // Check "certdb" variable's existence. + // If it doesn't exist, then create a new one with + // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set. + // + Status = FindVariable ( + EFI_CERT_DB_NAME, + &gEfiCertDbGuid, + &Variable, + &mVariableModuleGlobal->VariableGlobal, + FALSE + ); + + if (Variable.CurrPtr == NULL) { + VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + ListSize = 0; + Status = UpdateVariable ( + EFI_CERT_DB_NAME, + &gEfiCertDbGuid, + &ListSize, + sizeof (UINT32), + VarAttr, + 0, + 0, + &Variable, + NULL + ); + + } + return Status; } @@ -887,7 +918,16 @@ ProcessVarWithPk ( // Verify against X509 Cert PK. // Del = FALSE; - Status = VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, TRUE, &Del); + Status = VerifyTimeBasedPayload ( + VariableName, + VendorGuid, + Data, + DataSize, + Variable, + Attributes, + AuthVarTypePk, + &Del + ); if (!EFI_ERROR (Status)) { // // If delete PK in user mode, need change to setup mode. @@ -1084,7 +1124,16 @@ ProcessVarWithKek ( // // Time-based, verify against X509 Cert KEK. // - return VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, FALSE, NULL); + return VerifyTimeBasedPayload ( + VariableName, + VendorGuid, + Data, + DataSize, + Variable, + Attributes, + AuthVarTypeKek, + NULL + ); } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) { // // Counter-based, verify against RSA2048 Cert KEK. @@ -1255,7 +1304,16 @@ ProcessVariable ( // Process Time-based Authenticated variable. // if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { - return VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, FALSE, NULL); + return VerifyTimeBasedPayload ( + VariableName, + VendorGuid, + Data, + DataSize, + Variable, + Attributes, + AuthVarTypePriv, + NULL + ); } // @@ -1489,6 +1547,470 @@ CompareTimeStamp ( return (BOOLEAN) (FirstTime->Second <= SecondTime->Second); } +/** + Find matching signer's certificates for common authenticated variable + by corresponding VariableName and VendorGuid from "certdb". + + The data format of "certdb": + // + // UINT32 CertDbListSize; + // /// AUTH_CERT_DB_DATA Certs1[]; + // /// AUTH_CERT_DB_DATA Certs2[]; + // /// ... + // /// AUTH_CERT_DB_DATA Certsn[]; + // + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + @param[in] Data Pointer to variable "certdb". + @param[in] DataSize Size of variable "certdb". + @param[out] CertOffset Offset of matching CertData, from starting of Data. + @param[out] CertDataSize Length of CertData in bytes. + @param[out] CertNodeOffset Offset of matching AUTH_CERT_DB_DATA , from + starting of Data. + @param[out] CertNodeSize Length of AUTH_CERT_DB_DATA in bytes. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_NOT_FOUND Fail to find matching certs. + @retval EFI_SUCCESS Find matching certs and output parameters. + +**/ +EFI_STATUS +FindCertsFromDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT8 *Data, + IN UINTN DataSize, + OUT UINT32 *CertOffset, OPTIONAL + OUT UINT32 *CertDataSize, OPTIONAL + OUT UINT32 *CertNodeOffset,OPTIONAL + OUT UINT32 *CertNodeSize OPTIONAL + ) +{ + UINT32 Offset; + AUTH_CERT_DB_DATA *Ptr; + UINT32 CertSize; + UINT32 NameSize; + UINT32 NodeSize; + UINT32 CertDbListSize; + + if ((VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether DataSize matches recorded CertDbListSize. + // + if (DataSize < sizeof (UINT32)) { + return EFI_INVALID_PARAMETER; + } + + CertDbListSize = ReadUnaligned32 ((UINT32 *) Data); + + if (CertDbListSize != (UINT32) DataSize) { + return EFI_INVALID_PARAMETER; + } + + Offset = sizeof (UINT32); + + // + // Get corresponding certificates by VendorGuid and VariableName. + // + while (Offset < (UINT32) DataSize) { + Ptr = (AUTH_CERT_DB_DATA *) (Data + Offset); + // + // Check whether VendorGuid matches. + // + if (CompareGuid (&Ptr->VendorGuid, VendorGuid)) { + NodeSize = ReadUnaligned32 (&Ptr->CertNodeSize); + NameSize = ReadUnaligned32 (&Ptr->NameSize); + CertSize = ReadUnaligned32 (&Ptr->CertDataSize); + + if (NodeSize != sizeof (EFI_GUID) + sizeof (UINT32) * 3 + CertSize + + sizeof (CHAR16) * NameSize) { + return EFI_INVALID_PARAMETER; + } + + Offset = Offset + sizeof (EFI_GUID) + sizeof (UINT32) * 3; + // + // Check whether VariableName matches. + // + if ((NameSize == StrLen (VariableName)) && + (CompareMem (Data + Offset, VariableName, NameSize * sizeof (CHAR16)) == 0)) { + Offset = Offset + NameSize * sizeof (CHAR16); + + if (CertOffset != NULL) { + *CertOffset = Offset; + } + + if (CertDataSize != NULL) { + *CertDataSize = CertSize; + } + + if (CertNodeOffset != NULL) { + *CertNodeOffset = (UINT32) ((UINT8 *) Ptr - Data); + } + + if (CertNodeSize != NULL) { + *CertNodeSize = NodeSize; + } + + return EFI_SUCCESS; + } else { + Offset = Offset + NameSize * sizeof (CHAR16) + CertSize; + } + } else { + NodeSize = ReadUnaligned32 (&Ptr->CertNodeSize); + Offset = Offset + NodeSize; + } + } + + return EFI_NOT_FOUND; +} + +/** + Retrieve signer's certificates for common authenticated variable + by corresponding VariableName and VendorGuid from "certdb". + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + @param[out] CertData Pointer to signer's certificates. + @param[out] CertDataSize Length of CertData in bytes. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_NOT_FOUND Fail to find "certdb" or matching certs. + @retval EFI_SUCCESS Get signer's certificates successfully. + +**/ +EFI_STATUS +GetCertsFromDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT8 **CertData, + OUT UINT32 *CertDataSize + ) +{ + VARIABLE_POINTER_TRACK CertDbVariable; + EFI_STATUS Status; + UINT8 *Data; + UINTN DataSize; + UINT32 CertOffset; + + if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL) || (CertDataSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get variable "certdb". + // + Status = FindVariable ( + EFI_CERT_DB_NAME, + &gEfiCertDbGuid, + &CertDbVariable, + &mVariableModuleGlobal->VariableGlobal, + FALSE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DataSize = DataSizeOfVariable (CertDbVariable.CurrPtr); + Data = GetVariableDataPtr (CertDbVariable.CurrPtr); + if ((DataSize == 0) || (Data == NULL)) { + ASSERT (FALSE); + return EFI_NOT_FOUND; + } + + Status = FindCertsFromDb ( + VariableName, + VendorGuid, + Data, + DataSize, + &CertOffset, + CertDataSize, + NULL, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + *CertData = Data + CertOffset; + return EFI_SUCCESS; +} + +/** + Delete matching signer's certificates when deleting common authenticated + variable by corresponding VariableName and VendorGuid from "certdb". + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_NOT_FOUND Fail to find "certdb" or matching certs. + @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources. + @retval EFI_SUCCESS The operation is completed successfully. + +**/ +EFI_STATUS +DeleteCertsFromDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ) +{ + VARIABLE_POINTER_TRACK CertDbVariable; + EFI_STATUS Status; + UINT8 *Data; + UINTN DataSize; + UINT32 VarAttr; + UINT32 CertNodeOffset; + UINT32 CertNodeSize; + UINT8 *NewCertDb; + UINT32 NewCertDbSize; + + if ((VariableName == NULL) || (VendorGuid == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get variable "certdb". + // + Status = FindVariable ( + EFI_CERT_DB_NAME, + &gEfiCertDbGuid, + &CertDbVariable, + &mVariableModuleGlobal->VariableGlobal, + FALSE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DataSize = DataSizeOfVariable (CertDbVariable.CurrPtr); + Data = GetVariableDataPtr (CertDbVariable.CurrPtr); + if ((DataSize == 0) || (Data == NULL)) { + ASSERT (FALSE); + return EFI_NOT_FOUND; + } + + if (DataSize == sizeof (UINT32)) { + // + // There is no certs in certdb. + // + return EFI_SUCCESS; + } + + // + // Get corresponding cert node from certdb. + // + Status = FindCertsFromDb ( + VariableName, + VendorGuid, + Data, + DataSize, + NULL, + NULL, + &CertNodeOffset, + &CertNodeSize + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if (DataSize < (CertNodeOffset + CertNodeSize)) { + return EFI_NOT_FOUND; + } + + // + // Construct new data content of variable "certdb". + // + NewCertDbSize = (UINT32) DataSize - CertNodeSize; + NewCertDb = AllocateZeroPool (NewCertDbSize); + if (NewCertDb == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Copy the DB entries before deleting node. + // + CopyMem (NewCertDb, Data, CertNodeOffset); + // + // Update CertDbListSize. + // + CopyMem (NewCertDb, &NewCertDbSize, sizeof (UINT32)); + // + // Copy the DB entries after deleting node. + // + if (DataSize > (CertNodeOffset + CertNodeSize)) { + CopyMem ( + NewCertDb + CertNodeOffset, + Data + CertNodeOffset + CertNodeSize, + DataSize - CertNodeOffset - CertNodeSize + ); + } + + // + // Set "certdb". + // + VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + Status = UpdateVariable ( + EFI_CERT_DB_NAME, + &gEfiCertDbGuid, + NewCertDb, + NewCertDbSize, + VarAttr, + 0, + 0, + &CertDbVariable, + NULL + ); + + FreePool (NewCertDb); + return Status; +} + +/** + Insert signer's certificates for common authenticated variable with VariableName + and VendorGuid in AUTH_CERT_DB_DATA to "certdb". + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + @param[in] CertData Pointer to signer's certificates. + @param[in] CertDataSize Length of CertData in bytes. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_ACCESS_DENIED An AUTH_CERT_DB_DATA entry with same VariableName + and VendorGuid already exists. + @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources. + @retval EFI_SUCCESS Insert an AUTH_CERT_DB_DATA entry to "certdb" + +**/ +EFI_STATUS +InsertCertsToDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT8 *CertData, + IN UINTN CertDataSize + ) +{ + VARIABLE_POINTER_TRACK CertDbVariable; + EFI_STATUS Status; + UINT8 *Data; + UINTN DataSize; + UINT32 VarAttr; + UINT8 *NewCertDb; + UINT32 NewCertDbSize; + UINT32 CertNodeSize; + UINT32 NameSize; + AUTH_CERT_DB_DATA *Ptr; + + if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get variable "certdb". + // + Status = FindVariable ( + EFI_CERT_DB_NAME, + &gEfiCertDbGuid, + &CertDbVariable, + &mVariableModuleGlobal->VariableGlobal, + FALSE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DataSize = DataSizeOfVariable (CertDbVariable.CurrPtr); + Data = GetVariableDataPtr (CertDbVariable.CurrPtr); + if ((DataSize == 0) || (Data == NULL)) { + ASSERT (FALSE); + return EFI_NOT_FOUND; + } + + // + // Find whether matching cert node already exists in "certdb". + // If yes return error. + // + Status = FindCertsFromDb ( + VariableName, + VendorGuid, + Data, + DataSize, + NULL, + NULL, + NULL, + NULL + ); + + if (!EFI_ERROR (Status)) { + ASSERT (FALSE); + return EFI_ACCESS_DENIED; + } + + // + // Construct new data content of variable "certdb". + // + NameSize = (UINT32) StrLen (VariableName); + CertNodeSize = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + NameSize * sizeof (CHAR16); + NewCertDbSize = (UINT32) DataSize + CertNodeSize; + NewCertDb = AllocateZeroPool (NewCertDbSize); + if (NewCertDb == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Copy the DB entries before deleting node. + // + CopyMem (NewCertDb, Data, DataSize); + // + // Update CertDbListSize. + // + CopyMem (NewCertDb, &NewCertDbSize, sizeof (UINT32)); + // + // Construct new cert node. + // + Ptr = (AUTH_CERT_DB_DATA *) (NewCertDb + DataSize); + CopyGuid (&Ptr->VendorGuid, VendorGuid); + CopyMem (&Ptr->CertNodeSize, &CertNodeSize, sizeof (UINT32)); + CopyMem (&Ptr->NameSize, &NameSize, sizeof (UINT32)); + CopyMem (&Ptr->CertDataSize, &CertDataSize, sizeof (UINT32)); + + CopyMem ( + (UINT8 *) Ptr + sizeof (AUTH_CERT_DB_DATA), + VariableName, + NameSize * sizeof (CHAR16) + ); + + CopyMem ( + (UINT8 *) Ptr + sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16), + CertData, + CertDataSize + ); + + // + // Set "certdb". + // + VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + Status = UpdateVariable ( + EFI_CERT_DB_NAME, + &gEfiCertDbGuid, + NewCertDb, + NewCertDbSize, + VarAttr, + 0, + 0, + &CertDbVariable, + NULL + ); + + FreePool (NewCertDb); + return Status; +} + /** Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set @@ -1499,7 +2021,7 @@ CompareTimeStamp ( data, this value contains the required size. @param[in] Variable The variable information which is used to keep track of variable usage. @param[in] Attributes Attribute value of the variable. - @param[in] Pk Verify against PK or KEK database. + @param[in] AuthVarType Verify against PK or KEK database or private database. @param[out] VarDel Delete the variable or not. @retval EFI_INVALID_PARAMETER Invalid parameter. @@ -1518,7 +2040,7 @@ VerifyTimeBasedPayload ( IN UINTN DataSize, IN VARIABLE_POINTER_TRACK *Variable, IN UINT32 Attributes, - IN BOOLEAN Pk, + IN AUTHVAR_TYPE AuthVarType, OUT BOOLEAN *VarDel ) { @@ -1532,7 +2054,6 @@ VerifyTimeBasedPayload ( UINT32 Attr; UINT32 SigDataSize; UINT32 KekDataSize; - BOOLEAN Result; BOOLEAN VerifyStatus; EFI_STATUS Status; EFI_SIGNATURE_LIST *CertList; @@ -1544,12 +2065,19 @@ VerifyTimeBasedPayload ( VARIABLE_POINTER_TRACK PkVariable; UINT8 *Buffer; UINTN Length; + UINT8 *SignerCerts; + UINT8 *WrapSigData; + UINTN CertStackSize; + UINT8 *CertsInCertDb; + UINT32 CertsSizeinDb; - Result = FALSE; VerifyStatus = FALSE; CertData = NULL; NewData = NULL; Attr = Attributes; + WrapSigData = NULL; + SignerCerts = NULL; + RootCert = NULL; // // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is @@ -1633,7 +2161,7 @@ VerifyTimeBasedPayload ( CopyMem (Buffer, PayloadPtr, PayloadSize); - if (Pk) { + if (AuthVarType == AuthVarTypePk) { // // Get platform key from variable. // @@ -1666,7 +2194,7 @@ VerifyTimeBasedPayload ( NewDataSize ); - } else { + } else if (AuthVarType == AuthVarTypeKek) { // // Get KEK database from variable. @@ -1718,10 +2246,85 @@ VerifyTimeBasedPayload ( KekDataSize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); } + } else if (AuthVarType == AuthVarTypePriv) { + + // + // Process common authenticated variable except PK/KEK/DB/DBX. + // Get signer's certificates from SignedData. + // + VerifyStatus = Pkcs7GetSigners ( + SigData, + SigDataSize, + &SignerCerts, + &CertStackSize, + &RootCert, + &RootCertSize + ); + if (!VerifyStatus) { + goto Exit; + } + + // + // Get previously stored signer's certificates from certdb for existing + // variable. Check whether they are identical with signer's certificates + // in SignedData. If not, return error immediately. + // + if ((Variable->CurrPtr != NULL)) { + VerifyStatus = FALSE; + + Status = GetCertsFromDb (VariableName, VendorGuid, &CertsInCertDb, &CertsSizeinDb); + if (EFI_ERROR (Status)) { + goto Exit; + } + + if ((CertStackSize != CertsSizeinDb) || + (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) { + goto Exit; + } + } + + VerifyStatus = Pkcs7Verify ( + SigData, + SigDataSize, + RootCert, + RootCertSize, + NewData, + NewDataSize + ); + if (!VerifyStatus) { + goto Exit; + } + + // + // Delete signer's certificates when delete the common authenticated variable. + // + if ((PayloadSize == 0) && (Variable->CurrPtr != NULL)) { + Status = DeleteCertsFromDb (VariableName, VendorGuid); + if (EFI_ERROR (Status)) { + VerifyStatus = FALSE; + goto Exit; + } + } else if (Variable->CurrPtr == NULL) { + // + // Insert signer's certificates when adding a new common authenticated variable. + // + Status = InsertCertsToDb (VariableName, VendorGuid, SignerCerts, CertStackSize); + if (EFI_ERROR (Status)) { + VerifyStatus = FALSE; + goto Exit; + } + } + } else { + return EFI_SECURITY_VIOLATION; } Exit: + if (AuthVarType == AuthVarTypePriv) { + Pkcs7FreeSigners (RootCert); + Pkcs7FreeSigners (SignerCerts); + } + if (!VerifyStatus) { return EFI_SECURITY_VIOLATION; } @@ -1738,15 +2341,16 @@ Exit: // // Final step: Update/Append Variable if it pass Pkcs7Verify // - return UpdateVariable ( - VariableName, - VendorGuid, - PayloadPtr, - PayloadSize, - Attributes, - 0, - 0, - Variable, - &CertData->TimeStamp - ); + return UpdateVariable ( + VariableName, + VendorGuid, + PayloadPtr, + PayloadSize, + Attributes, + 0, + 0, + Variable, + &CertData->TimeStamp + ); } + diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h b/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h index 9a022f38f9..4419c91744 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h @@ -2,7 +2,7 @@ The internal header file includes the common header files, defines internal structure and functions used by AuthService 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 @@ -56,6 +56,23 @@ typedef struct { UINT32 SigDataSize; } EFI_SIGNATURE_ITEM; +typedef enum { + AuthVarTypePk, + AuthVarTypeKek, + AuthVarTypePriv +} AUTHVAR_TYPE; + +#pragma pack(1) +typedef struct { + EFI_GUID VendorGuid; + UINT32 CertNodeSize; + UINT32 NameSize; + UINT32 CertDataSize; + /// CHAR16 VariableName[NameSize]; + /// UINT8 CertData[CertDataSize]; +} AUTH_CERT_DB_DATA; +#pragma pack() + /** Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set. @@ -247,7 +264,7 @@ CompareTimeStamp ( data, this value contains the required size. @param[in] Variable The variable information which is used to keep track of variable usage. @param[in] Attributes Attribute value of the variable. - @param[in] Pk Verify against PK or KEK database. + @param[in] AuthVarType Verify against PK or KEK database or private database. @param[out] VarDel Delete the variable or not. @retval EFI_INVALID_PARAMETER Invalid parameter. @@ -266,7 +283,7 @@ VerifyTimeBasedPayload ( IN UINTN DataSize, IN VARIABLE_POINTER_TRACK *Variable, IN UINT32 Attributes, - IN BOOLEAN Pk, + IN AUTHVAR_TYPE AuthVarType, OUT BOOLEAN *VarDel ); diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf index abe14abab3..7b15186353 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf @@ -75,6 +75,7 @@ gEfiSecureBootEnableDisableGuid gEfiCustomModeEnableGuid gEfiSystemNvDataFvGuid ## CONSUMES + gEfiCertDbGuid [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf index cd6457f8f4..a62fd43989 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf @@ -80,6 +80,7 @@ gEfiSecureBootEnableDisableGuid gEfiCustomModeEnableGuid gEfiSystemNvDataFvGuid ## CONSUMES + gEfiCertDbGuid [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize -- 2.39.2