4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Implement authentication services for the authenticated variable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync service in UEFI2.2.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncare licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwhich accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/// Global database array for scratch
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_GUID mSignatureSupport[SIGSUPPORT_NUM] = {EFI_CERT_RSA2048_SHA256_GUID, EFI_CERT_RSA2048_SHA1_GUID};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Public Exponent of RSA Key.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Initializes for authenticated varibale service.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The function successfully executed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate enough memory resources.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mVariableModuleGlobal->AuthenticatedVariableGuid[Physical] = &gEfiAuthenticatedVariableGuid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mVariableModuleGlobal->CertRsa2048Sha256Guid[Physical] = &gEfiCertRsa2048Sha256Guid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mVariableModuleGlobal->ImageSecurityDatabaseGuid[Physical] = &gEfiImageSecurityDatabaseGuid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initialize hash context.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mVariableModuleGlobal->HashContext[Physical] = AllocateRuntimePool (CtxSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (mVariableModuleGlobal->HashContext[Physical] != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check "AuthVarKeyDatabase" variable's existence.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mVariableModuleGlobal->VariableName[Physical][VAR_AUTH_KEY_DB],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Load database in global variable for cache.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check "SetupMode" variable's existence.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If it doesn't exist, check PK database's existence to determine the value.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mVariableModuleGlobal->VariableName[Physical][VAR_PLATFORM_KEY],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mVariableModuleGlobal->VariableName[Physical][VAR_SETUP_MODE],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check "SignatureSupport" variable's existence.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Add public key in store and return its index.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VirtualMode The current calling mode for this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Global The context of this Extended SAL Variable Services Class call.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PubKey The input pointer to Public Key data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The index of new added item.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Global->VariableName[VirtualMode][VAR_AUTH_KEY_DB],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check whether the public key entry does exist.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Ptr = Global->PubKeyStore, Index = 1; Index <= mPubKeyNumber; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CompareMem (Ptr, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Add public key in database.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Notes: Database is full, need enhancement here, currently just return 0.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Global->PubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update public key database variable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Global->VariableName[VirtualMode][VAR_AUTH_KEY_DB],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256 type.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Follow the steps in UEFI2.2.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VirtualMode The current calling mode for this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Global The context of this Extended SAL Variable Services Class call.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The pointer to data with AuthInfo.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DataSize The size of Data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PubKey The public key used for verification.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Invalid parameter.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SECURITY_VIOLATION Authentication failed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Authentication successful.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync !CompareGuid (&CertData->AuthInfo.CertType, Global->CertRsa2048Sha256Guid[VirtualMode])
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Hash data payload with SHA256.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Sha256Update (HashContext, Data + AUTHINFO_SIZE, (UINTN) (DataSize - AUTHINFO_SIZE));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Hash Monotonic Count.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Sha256Update (HashContext, &CertData->MonotonicCount, sizeof (UINT64));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generate & Initialize RSA Context.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set RSA Key Components.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = RsaSetKey (Rsa, RsaKeyN, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Verify the signature.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Update platform mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VirtualMode The current calling mode for this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Global The context of this Extended SAL Variable Services Class call.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Mode SETUP_MODE or USER_MODE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process variable with platform key for verification.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VariableName The name of Variable to be found.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VendorGuid The variable vendor GUID.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The data pointer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DataSize The size of Data found. If size is less than the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync data, this value contains the required size.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VirtualMode The current calling mode for this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Global The context of this Extended SAL Variable Services Class call.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Variable The variable information which is used to keep track of variable usage.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Attributes The attribute value of the variable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IsPk Indicates whether to process pk.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Invalid parameter.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync check carried out by the firmware.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The variable passed validation successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // In user mode, PK and KEK should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get platform key from variable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Global->VariableName[VirtualMode][VAR_PLATFORM_KEY],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldPkList = (EFI_SIGNATURE_LIST *) Global->KeyList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, OldPkData->SignatureData);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If delete PK in user mode, need change to setup mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UpdatePlatformMode (VirtualMode, Global, SETUP_MODE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, VirtualMode, Global, Variable);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If enroll PK in setup mode, need change to user mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UpdatePlatformMode (VirtualMode, Global, USER_MODE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process variable with key exchange key for verification.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VariableName The name of Variable to be found.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VendorGuid The variable vendor GUID.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The data pointer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DataSize The size of Data found. If size is less than the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync data, this value contains the required size.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VirtualMode The current calling mode for this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Global The context of this Extended SAL Variable Services Class call.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Variable The variable information which is used to keep track of variable usage.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Attributes The attribute value of the variable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Invalid parameter.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SECURITY_VIOLATION The variable did NOT pass the validation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync check carried out by the firmware.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The variable passed validation successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get KEK database from variable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Global->VariableName[VirtualMode][VAR_KEY_EXCHANGE_KEY],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Enumerate all Kek items in this list to verify the variable certificate data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If anyone is authenticated successfully, it means the variable is correct!
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, CertBlock->PublicKey);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If in setup mode, no authentication needed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set, and return the index of associated public key.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The data pointer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DataSize The size of Data found. If size is less than the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync data, this value contains the required size.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] VirtualMode The current calling mode for this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Global The context of this Extended SAL Variable Services Class call.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Variable The variable information which is used to keep track of variable usage.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Attributes The attribute value of the variable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] KeyIndex The output index of corresponding public key in database.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] MonotonicCount The output value of corresponding Monotonic Count.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Invalid parameter.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_WRITE_PROTECTED The variable is write-protected and needs authentication with
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync set, but the AuthInfo does NOT pass the validation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync check carried out by the firmware.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The variable is not write-protected, or passed validation successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&VariableHeader, sizeof (VARIABLE_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine current operation type.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Valid &&(VariableHeader.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Valid && (VariableHeader.Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the variable is already write-protected, it always needs authentication before update.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // That means it is not authenticated variable, just return EFI_SUCCESS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get PubKey and check Monotonic Count value corresponding to the variable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update Monotonic Count value.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check input PubKey.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CompareMem (PubKey, Global->PubKeyStore + (*KeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE, EFI_CERT_TYPE_RSA2048_SIZE) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compare the current monotonic count and ensure that it is greater than the last SetVariable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CertData->MonotonicCount <= VariableHeader.MonotonicCount) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Verify the certificate in Data payload.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = VerifyDataPayload (VirtualMode, Global, Data, DataSize, PubKey);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Now, the signature has been verified!
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update public key database variable if need and return the index.