X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=SecurityPkg%2FVariableAuthenticated%2FEsalVariableDxeSal%2FAuthService.c;fp=SecurityPkg%2FVariableAuthenticated%2FEsalVariableDxeSal%2FAuthService.c;h=0000000000000000000000000000000000000000;hp=87994587da06fe4c2c72ba659ea3ea10a14971b8;hb=4cecd19a44dca3b02f8cf7359420b6271518e7dc;hpb=dbf9cc87cb5c0c837c2acfd12dc0e3f8632ae7e6 diff --git a/SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/AuthService.c b/SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/AuthService.c deleted file mode 100644 index 87994587da..0000000000 --- a/SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/AuthService.c +++ /dev/null @@ -1,886 +0,0 @@ -/** @file - Implement authentication services for the authenticated variable - service in UEFI2.2. - -Copyright (c) 2009 - 2018, 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 "Variable.h" -#include "AuthService.h" - -/// -/// Global database array for scratch -/// -UINT32 mPubKeyNumber; -UINT32 mPlatformMode; -EFI_GUID mSignatureSupport[SIGSUPPORT_NUM] = {EFI_CERT_RSA2048_SHA256_GUID, EFI_CERT_RSA2048_SHA1_GUID}; -// -// Public Exponent of RSA Key. -// -CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 }; - -/** - Initializes for authenticated varibale service. - - @retval EFI_SUCCESS The function successfully executed. - @retval EFI_OUT_OF_RESOURCES Failed to allocate enough memory resources. - -**/ -EFI_STATUS -AutenticatedVariableServiceInitialize ( - VOID - ) -{ - EFI_STATUS Status; - VARIABLE_POINTER_TRACK Variable; - UINT8 VarValue; - UINT32 VarAttr; - UINTN DataSize; - UINTN CtxSize; - AUTHENTICATED_VARIABLE_HEADER VariableHeader; - BOOLEAN Valid; - - ZeroMem (&VariableHeader, sizeof (AUTHENTICATED_VARIABLE_HEADER)); - - mVariableModuleGlobal->AuthenticatedVariableGuid[Physical] = &gEfiAuthenticatedVariableGuid; - mVariableModuleGlobal->CertRsa2048Sha256Guid[Physical] = &gEfiCertRsa2048Sha256Guid; - mVariableModuleGlobal->ImageSecurityDatabaseGuid[Physical] = &gEfiImageSecurityDatabaseGuid; - - // - // Initialize hash context. - // - CtxSize = Sha256GetContextSize (); - mVariableModuleGlobal->HashContext[Physical] = AllocateRuntimePool (CtxSize); - ASSERT (mVariableModuleGlobal->HashContext[Physical] != NULL); - // - // Check "AuthVarKeyDatabase" variable's existence. - // If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. - // - Status = FindVariable ( - mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB], - &gEfiAuthenticatedVariableGuid, - &Variable, - &mVariableModuleGlobal->VariableGlobal[Physical], - mVariableModuleGlobal->FvbInstance - ); - - if (Variable.CurrPtr == 0x0) { - VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS; - VarValue = 0; - mPubKeyNumber = 0; - Status = UpdateVariable ( - mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB], - &gEfiAuthenticatedVariableGuid, - &VarValue, - sizeof(UINT8), - VarAttr, - 0, - 0, - FALSE, - mVariableModuleGlobal, - &Variable - ); - if (EFI_ERROR (Status)) { - return Status; - } - } else { - // - // Load database in global variable for cache. - // - Valid = IsValidVariableHeader ( - Variable.CurrPtr, - Variable.Volatile, - &mVariableModuleGlobal->VariableGlobal[Physical], - mVariableModuleGlobal->FvbInstance, - &VariableHeader - ); - ASSERT (Valid); - - DataSize = DataSizeOfVariable (&VariableHeader); - ASSERT (DataSize <= MAX_KEYDB_SIZE); - GetVariableDataPtr ( - Variable.CurrPtr, - Variable.Volatile, - &mVariableModuleGlobal->VariableGlobal[Physical], - mVariableModuleGlobal->FvbInstance, - (CHAR16 *) mVariableModuleGlobal->PubKeyStore - ); - - mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE); - } - // - // Check "SetupMode" variable's existence. - // If it doesn't exist, check PK database's existence to determine the value. - // Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. - // - Status = FindVariable ( - mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE], - &gEfiGlobalVariableGuid, - &Variable, - &mVariableModuleGlobal->VariableGlobal[Physical], - mVariableModuleGlobal->FvbInstance - ); - - if (Variable.CurrPtr == 0x0) { - Status = FindVariable ( - mVariableModuleGlobal->VariableName[Physical][VAR_PLATFORM_KEY], - &gEfiGlobalVariableGuid, - &Variable, - &mVariableModuleGlobal->VariableGlobal[Physical], - mVariableModuleGlobal->FvbInstance - ); - if (Variable.CurrPtr == 0x0) { - mPlatformMode = SETUP_MODE; - } else { - mPlatformMode = USER_MODE; - } - - VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS; - Status = UpdateVariable ( - mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE], - &gEfiGlobalVariableGuid, - &mPlatformMode, - sizeof(UINT8), - VarAttr, - 0, - 0, - FALSE, - mVariableModuleGlobal, - &Variable - ); - if (EFI_ERROR (Status)) { - return Status; - } - } else { - GetVariableDataPtr ( - Variable.CurrPtr, - Variable.Volatile, - &mVariableModuleGlobal->VariableGlobal[Physical], - mVariableModuleGlobal->FvbInstance, - (CHAR16 *) &mPlatformMode - ); - } - // - // Check "SignatureSupport" variable's existence. - // If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. - // - Status = FindVariable ( - EFI_SIGNATURE_SUPPORT_NAME, - &gEfiGlobalVariableGuid, - &Variable, - &mVariableModuleGlobal->VariableGlobal[Physical], - mVariableModuleGlobal->FvbInstance - ); - - if (Variable.CurrPtr == 0x0) { - VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS; - Status = UpdateVariable ( - EFI_SIGNATURE_SUPPORT_NAME, - &gEfiGlobalVariableGuid, - mSignatureSupport, - SIGSUPPORT_NUM * sizeof(EFI_GUID), - VarAttr, - 0, - 0, - FALSE, - mVariableModuleGlobal, - &Variable - ); - } - - return Status; -} - -/** - Add public key in store and return its index. - - @param[in] VirtualMode The current calling mode for this function. - @param[in] Global The context of this Extended SAL Variable Services Class call. - @param[in] PubKey The input pointer to Public Key data. - - @return The index of new added item. - -**/ -UINT32 -AddPubKeyInStore ( - IN BOOLEAN VirtualMode, - IN ESAL_VARIABLE_GLOBAL *Global, - IN UINT8 *PubKey - ) -{ - EFI_STATUS Status; - BOOLEAN IsFound; - UINT32 Index; - VARIABLE_POINTER_TRACK Variable; - UINT8 *Ptr; - - if (PubKey == NULL) { - return 0; - } - - Status = FindVariable ( - Global->VariableName[VirtualMode][VAR_AUTH_KEY_DB], - Global->AuthenticatedVariableGuid[VirtualMode], - &Variable, - &Global->VariableGlobal[VirtualMode], - Global->FvbInstance - ); - ASSERT_EFI_ERROR (Status); - // - // Check whether the public key entry does exist. - // - IsFound = FALSE; - for (Ptr = Global->PubKeyStore, Index = 1; Index <= mPubKeyNumber; Index++) { - if (CompareMem (Ptr, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) { - IsFound = TRUE; - break; - } - Ptr += EFI_CERT_TYPE_RSA2048_SIZE; - } - - if (!IsFound) { - // - // Add public key in database. - // - if (mPubKeyNumber == MAX_KEY_NUM) { - // - // Notes: Database is full, need enhancement here, currently just return 0. - // - return 0; - } - - CopyMem (Global->PubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE); - Index = ++mPubKeyNumber; - // - // Update public key database variable. - // - Status = UpdateVariable ( - Global->VariableName[VirtualMode][VAR_AUTH_KEY_DB], - Global->AuthenticatedVariableGuid[VirtualMode], - Global->PubKeyStore, - mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, - 0, - 0, - VirtualMode, - Global, - &Variable - ); - ASSERT_EFI_ERROR (Status); - } - - return Index; -} - -/** - Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256 type. - Follow the steps in UEFI2.2. - - @param[in] VirtualMode The current calling mode for this function. - @param[in] Global The context of this Extended SAL Variable Services Class call. - @param[in] Data The pointer to data with AuthInfo. - @param[in] DataSize The size of Data. - @param[in] PubKey The public key used for verification. - - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_SECURITY_VIOLATION Authentication failed. - @retval EFI_SUCCESS Authentication successful. - -**/ -EFI_STATUS -VerifyDataPayload ( - IN BOOLEAN VirtualMode, - IN ESAL_VARIABLE_GLOBAL *Global, - IN UINT8 *Data, - IN UINTN DataSize, - IN UINT8 *PubKey - ) -{ - BOOLEAN Status; - EFI_VARIABLE_AUTHENTICATION *CertData; - EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock; - UINT8 Digest[SHA256_DIGEST_SIZE]; - VOID *Rsa; - VOID *HashContext; - - Rsa = NULL; - CertData = NULL; - CertBlock = NULL; - - if (Data == NULL || PubKey == NULL) { - return EFI_INVALID_PARAMETER; - } - - CertData = (EFI_VARIABLE_AUTHENTICATION *) Data; - CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData); - - // - // wCertificateType should be WIN_CERT_TYPE_EFI_GUID. - // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256. - // - if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) || - !CompareGuid (&CertData->AuthInfo.CertType, Global->CertRsa2048Sha256Guid[VirtualMode]) - ) { - // - // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION. - // - return EFI_SECURITY_VIOLATION; - } - - // - // Hash data payload with SHA256. - // - ZeroMem (Digest, SHA256_DIGEST_SIZE); - HashContext = Global->HashContext[VirtualMode]; - Status = Sha256Init (HashContext); - if (!Status) { - goto Done; - } - Status = Sha256Update (HashContext, Data + AUTHINFO_SIZE, (UINTN) (DataSize - AUTHINFO_SIZE)); - if (!Status) { - goto Done; - } - // - // Hash Monotonic Count. - // - Status = Sha256Update (HashContext, &CertData->MonotonicCount, sizeof (UINT64)); - if (!Status) { - goto Done; - } - Status = Sha256Final (HashContext, Digest); - if (!Status) { - goto Done; - } - // - // Generate & Initialize RSA Context. - // - Rsa = RsaNew (); - ASSERT (Rsa != NULL); - // - // Set RSA Key Components. - // NOTE: Only N and E are needed to be set as RSA public key for signature verification. - // - Status = RsaSetKey (Rsa, RsaKeyN, PubKey, EFI_CERT_TYPE_RSA2048_SIZE); - if (!Status) { - goto Done; - } - Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE)); - if (!Status) { - goto Done; - } - // - // Verify the signature. - // - Status = RsaPkcs1Verify ( - Rsa, - Digest, - SHA256_DIGEST_SIZE, - CertBlock->Signature, - EFI_CERT_TYPE_RSA2048_SHA256_SIZE - ); - -Done: - if (Rsa != NULL) { - RsaFree (Rsa); - } - if (Status) { - return EFI_SUCCESS; - } else { - return EFI_SECURITY_VIOLATION; - } -} - - -/** - Update platform mode. - - @param[in] VirtualMode The current calling mode for this function. - @param[in] Global The context of this Extended SAL Variable Services Class call. - @param[in] Mode SETUP_MODE or USER_MODE. - -**/ -VOID -UpdatePlatformMode ( - IN BOOLEAN VirtualMode, - IN ESAL_VARIABLE_GLOBAL *Global, - IN UINT32 Mode - ) -{ - EFI_STATUS Status; - VARIABLE_POINTER_TRACK Variable; - UINT32 VarAttr; - - Status = FindVariable ( - Global->VariableName[VirtualMode][VAR_SETUP_MODE], - Global->GlobalVariableGuid[VirtualMode], - &Variable, - &Global->VariableGlobal[VirtualMode], - Global->FvbInstance - ); - ASSERT_EFI_ERROR (Status); - - mPlatformMode = Mode; - VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS; - Status = UpdateVariable ( - Global->VariableName[VirtualMode][VAR_SETUP_MODE], - Global->GlobalVariableGuid[VirtualMode], - &mPlatformMode, - sizeof(UINT8), - VarAttr, - 0, - 0, - VirtualMode, - Global, - &Variable - ); - ASSERT_EFI_ERROR (Status); -} - -/** - Process variable with platform key for verification. - - @param[in] VariableName The name of Variable to be found. - @param[in] VendorGuid The variable vendor GUID. - @param[in] Data The data pointer. - @param[in] DataSize The size of Data found. If size is less than the - data, this value contains the required size. - @param[in] VirtualMode The current calling mode for this function. - @param[in] Global The context of this Extended SAL Variable Services Class call. - @param[in] Variable The variable information which is used to keep track of variable usage. - @param[in] Attributes The attribute value of the variable. - @param[in] IsPk Indicates whether to process pk. - - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation - check carried out by the firmware. - @retval EFI_SUCCESS The variable passed validation successfully. - -**/ -EFI_STATUS -ProcessVarWithPk ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN VOID *Data, - IN UINTN DataSize, - IN BOOLEAN VirtualMode, - IN ESAL_VARIABLE_GLOBAL *Global, - IN VARIABLE_POINTER_TRACK *Variable, - IN UINT32 Attributes OPTIONAL, - IN BOOLEAN IsPk - ) -{ - EFI_STATUS Status; - VARIABLE_POINTER_TRACK PkVariable; - EFI_SIGNATURE_LIST *OldPkList; - EFI_SIGNATURE_DATA *OldPkData; - EFI_VARIABLE_AUTHENTICATION *CertData; - AUTHENTICATED_VARIABLE_HEADER VariableHeader; - BOOLEAN Valid; - - OldPkList = NULL; - ZeroMem (&VariableHeader, sizeof (AUTHENTICATED_VARIABLE_HEADER)); - - if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) { - // - // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute. - // - return EFI_INVALID_PARAMETER; - } - - if (mPlatformMode == USER_MODE) { - if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) { - // - // In user mode, PK and KEK should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute. - // - return EFI_INVALID_PARAMETER; - } - - CertData = (EFI_VARIABLE_AUTHENTICATION *) Data; - - if (Variable->CurrPtr != 0x0) { - Valid = IsValidVariableHeader ( - Variable->CurrPtr, - Variable->Volatile, - &Global->VariableGlobal[VirtualMode], - Global->FvbInstance, - &VariableHeader - ); - ASSERT (Valid); - - if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) { - // - // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION. - // - return EFI_SECURITY_VIOLATION; - } - } - // - // Get platform key from variable. - // - Status = FindVariable ( - Global->VariableName[VirtualMode][VAR_PLATFORM_KEY], - Global->GlobalVariableGuid[VirtualMode], - &PkVariable, - &Global->VariableGlobal[VirtualMode], - Global->FvbInstance - ); - ASSERT_EFI_ERROR (Status); - - ZeroMem (Global->KeyList, MAX_KEYDB_SIZE); - GetVariableDataPtr ( - PkVariable.CurrPtr, - PkVariable.Volatile, - &Global->VariableGlobal[VirtualMode], - Global->FvbInstance, - (CHAR16 *) Global->KeyList - ); - - OldPkList = (EFI_SIGNATURE_LIST *) Global->KeyList; - OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize); - Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, OldPkData->SignatureData); - if (!EFI_ERROR (Status)) { - Status = UpdateVariable ( - VariableName, - VendorGuid, - (UINT8*)Data + AUTHINFO_SIZE, - DataSize - AUTHINFO_SIZE, - Attributes, - 0, - CertData->MonotonicCount, - VirtualMode, - Global, - Variable - ); - - if (!EFI_ERROR (Status)) { - // - // If delete PK in user mode, need change to setup mode. - // - if ((DataSize == AUTHINFO_SIZE) && IsPk) { - UpdatePlatformMode (VirtualMode, Global, SETUP_MODE); - } - } - } - } else { - Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, VirtualMode, Global, Variable); - // - // If enroll PK in setup mode, need change to user mode. - // - if ((DataSize != 0) && IsPk) { - UpdatePlatformMode (VirtualMode, Global, USER_MODE); - } - } - - return Status; -} - -/** - Process variable with key exchange key for verification. - - @param[in] VariableName The name of Variable to be found. - @param[in] VendorGuid The variable vendor GUID. - @param[in] Data The data pointer. - @param[in] DataSize The size of Data found. If size is less than the - data, this value contains the required size. - @param[in] VirtualMode The current calling mode for this function. - @param[in] Global The context of this Extended SAL Variable Services Class call. - @param[in] Variable The variable information which is used to keep track of variable usage. - @param[in] Attributes The attribute value of the variable. - - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_SECURITY_VIOLATION The variable did NOT pass the validation - check carried out by the firmware. - @retval EFI_SUCCESS The variable passed validation successfully. - -**/ -EFI_STATUS -ProcessVarWithKek ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN VOID *Data, - IN UINTN DataSize, - IN BOOLEAN VirtualMode, - IN ESAL_VARIABLE_GLOBAL *Global, - IN VARIABLE_POINTER_TRACK *Variable, - IN UINT32 Attributes OPTIONAL - ) -{ - EFI_STATUS Status; - VARIABLE_POINTER_TRACK KekVariable; - EFI_SIGNATURE_LIST *KekList; - EFI_SIGNATURE_DATA *KekItem; - UINT32 KekCount; - EFI_VARIABLE_AUTHENTICATION *CertData; - EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock; - BOOLEAN IsFound; - UINT32 Index; - AUTHENTICATED_VARIABLE_HEADER VariableHeader; - BOOLEAN Valid; - - KekList = NULL; - ZeroMem (&VariableHeader, sizeof (AUTHENTICATED_VARIABLE_HEADER)); - - if (mPlatformMode == USER_MODE) { - if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) { - // - // In user mode, should set EFI_VARIABLE_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 != 0x0) { - Valid = IsValidVariableHeader ( - Variable->CurrPtr, - Variable->Volatile, - &Global->VariableGlobal[VirtualMode], - Global->FvbInstance, - &VariableHeader - ); - ASSERT (Valid); - - if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) { - // - // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION. - // - return EFI_SECURITY_VIOLATION; - } - } - // - // Get KEK database from variable. - // - Status = FindVariable ( - Global->VariableName[VirtualMode][VAR_KEY_EXCHANGE_KEY], - Global->GlobalVariableGuid[VirtualMode], - &KekVariable, - &Global->VariableGlobal[VirtualMode], - Global->FvbInstance - ); - ASSERT_EFI_ERROR (Status); - - ZeroMem (Global->KeyList, MAX_KEYDB_SIZE); - GetVariableDataPtr ( - KekVariable.CurrPtr, - KekVariable.Volatile, - &Global->VariableGlobal[VirtualMode], - Global->FvbInstance, - (CHAR16 *) Global->KeyList - ); - // - // Enumerate all Kek items in this list to verify the variable certificate data. - // If anyone is authenticated successfully, it means the variable is correct! - // - KekList = (EFI_SIGNATURE_LIST *) Global->KeyList; - IsFound = FALSE; - KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize; - KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize); - 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); - } - - if (!IsFound) { - return EFI_SECURITY_VIOLATION; - } - - Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, CertBlock->PublicKey); - if (!EFI_ERROR (Status)) { - Status = UpdateVariable ( - VariableName, - VendorGuid, - (UINT8*)Data + AUTHINFO_SIZE, - DataSize - AUTHINFO_SIZE, - Attributes, - 0, - CertData->MonotonicCount, - VirtualMode, - Global, - Variable - ); - } - } else { - // - // If in setup mode, no authentication needed. - // - Status = UpdateVariable ( - VariableName, - VendorGuid, - Data, - DataSize, - Attributes, - 0, - 0, - VirtualMode, - Global, - Variable - ); - } - - return Status; -} - -/** - Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set, and return the index of associated public key. - - @param[in] Data The data pointer. - @param[in] DataSize The size of Data found. If size is less than the - data, this value contains the required size. - @param[in] VirtualMode The current calling mode for this function. - @param[in] Global The context of this Extended SAL Variable Services Class call. - @param[in] Variable The variable information which is used to keep track of variable usage. - @param[in] Attributes The attribute value of the variable. - @param[out] KeyIndex The output index of corresponding public key in database. - @param[out] MonotonicCount The output value of corresponding Monotonic Count. - - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_WRITE_PROTECTED The variable is write-protected and needs authentication with - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. - @retval EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS - set, but the AuthInfo does NOT pass the validation - check carried out by the firmware. - @retval EFI_SUCCESS The variable is not write-protected, or passed validation successfully. - -**/ -EFI_STATUS -VerifyVariable ( - IN VOID *Data, - IN UINTN DataSize, - IN BOOLEAN VirtualMode, - IN ESAL_VARIABLE_GLOBAL *Global, - IN VARIABLE_POINTER_TRACK *Variable, - IN UINT32 Attributes OPTIONAL, - OUT UINT32 *KeyIndex OPTIONAL, - OUT UINT64 *MonotonicCount OPTIONAL - ) -{ - EFI_STATUS Status; - BOOLEAN IsDeletion; - BOOLEAN IsFirstTime; - UINT8 *PubKey; - EFI_VARIABLE_AUTHENTICATION *CertData; - EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock; - AUTHENTICATED_VARIABLE_HEADER VariableHeader; - BOOLEAN Valid; - - CertData = NULL; - CertBlock = NULL; - PubKey = NULL; - IsDeletion = FALSE; - Valid = FALSE; - - if (KeyIndex != NULL) { - *KeyIndex = 0; - } - // - // Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS. - // - ZeroMem (&VariableHeader, sizeof (AUTHENTICATED_VARIABLE_HEADER)); - if (Variable->CurrPtr != 0x0) { - Valid = IsValidVariableHeader ( - Variable->CurrPtr, - Variable->Volatile, - &Global->VariableGlobal[VirtualMode], - Global->FvbInstance, - &VariableHeader - ); - ASSERT (Valid); - } - - if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) { - if (KeyIndex == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Determine current operation type. - // - if (DataSize == AUTHINFO_SIZE) { - IsDeletion = TRUE; - } - // - // Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set. - // - if (Variable->CurrPtr == 0x0) { - IsFirstTime = TRUE; - } else if (Valid &&(VariableHeader.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) { - IsFirstTime = TRUE; - } else { - *KeyIndex = VariableHeader.PubKeyIndex; - IsFirstTime = FALSE; - } - } else if (Valid && (VariableHeader.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) { - // - // If the variable is already write-protected, it always needs authentication before update. - // - return EFI_WRITE_PROTECTED; - } else { - // - // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision. - // That means it is not authenticated variable, just return EFI_SUCCESS. - // - return EFI_SUCCESS; - } - - // - // Get PubKey and check Monotonic Count value corresponding to the variable. - // - CertData = (EFI_VARIABLE_AUTHENTICATION *) Data; - CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData); - PubKey = CertBlock->PublicKey; - - if (MonotonicCount != NULL) { - // - // Update Monotonic Count value. - // - *MonotonicCount = CertData->MonotonicCount; - } - - if (!IsFirstTime) { - // - // Check input PubKey. - // - if (CompareMem (PubKey, Global->PubKeyStore + (*KeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE, EFI_CERT_TYPE_RSA2048_SIZE) != 0) { - return EFI_SECURITY_VIOLATION; - } - // - // Compare the current monotonic count and ensure that it is greater than the last SetVariable - // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set. - // - if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) { - // - // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION. - // - return EFI_SECURITY_VIOLATION; - } - } - // - // Verify the certificate in Data payload. - // - Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, PubKey); - if (!EFI_ERROR (Status)) { - // - // Now, the signature has been verified! - // - if (IsFirstTime && !IsDeletion) { - // - // Update public key database variable if need and return the index. - // - *KeyIndex = AddPubKeyInStore (VirtualMode, Global, PubKey); - } - } - - return Status; -} -