summaryrefslogtreecommitdiffstats
path: root/SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/AuthService.c
diff options
context:
space:
mode:
Diffstat (limited to 'SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/AuthService.c')
-rw-r--r--SecurityPkg/VariableAuthenticated/EsalVariableDxeSal/AuthService.c886
1 files changed, 0 insertions, 886 deletions
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.<BR>
-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;
-}
-