From nobody Wed May 1 21:17:51 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+89424+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+89424+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1651255517; cv=none; d=zohomail.com; s=zohoarc; b=VIDR35DohzdtnsJ2zulModDtb2trS7IhOKCr/QQUlYuzv3LjPtPUNYLKCBKlPGcaxMegGzrE/otgarZ9msjVUEp4eo0gzXKP7GCJXeqjl3I1Qyh7xxXt9pvyCo9RoKeQlA+iVflLgpe9Z25rOSYB2cbJyJ9h5g15LKMDO9qBKtE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1651255517; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=qpJOKGcPf3GD+k1ZO2RpvZtCgVgkTmiYBaTeRKVUv8E=; b=fFhGGXUDZ0qjIo1RDRyWt/2EJPA5hz2Sn7GT9xHpxZw3EtlJrNDg3vr6B680hzGde7fXGM6XAGZLetJnsDebAVAXLynbFMKi1ahps0sZVgZhI/d+aJj/CvP3QgaOAbcgcRLtC4lp+P9e+6JcSbMNSB1O7/RjYAmTyxeo3+6aqQs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+89424+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1651255517679629.3450934218025; Fri, 29 Apr 2022 11:05:17 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id FXkoYY1788612x0J090sh0L3; Fri, 29 Apr 2022 11:05:17 -0700 X-Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web09.13406.1651255516658458883 for ; Fri, 29 Apr 2022 11:05:16 -0700 X-IronPort-AV: E=McAfee;i="6400,9594,10332"; a="248659175" X-IronPort-AV: E=Sophos;i="5.91,186,1647327600"; d="scan'208";a="248659175" X-Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Apr 2022 11:05:15 -0700 X-IronPort-AV: E=Sophos;i="5.91,186,1647327600"; d="scan'208";a="514955658" X-Received: from jvang-mobl.amr.corp.intel.com ([10.212.198.238]) by orsmga003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Apr 2022 11:05:15 -0700 From: "Judah Vang" To: devel@edk2.groups.io Cc: Jian J Wang , Liming Gao , Nishant C Mistry Subject: [edk2-devel] [Patch v2 06/28] MdeModulePkg: Add new include files Date: Fri, 29 Apr 2022 11:04:08 -0700 Message-Id: <20220429180430.3292-7-judah.vang@intel.com> In-Reply-To: <20220429180430.3292-1-judah.vang@intel.com> References: <20220429180430.3292-1-judah.vang@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,judah.vang@intel.com X-Gm-Message-State: ceuitmpc26UXr6UPIFyONuAMx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1651255517; bh=I5SofvQ40iVD9oJh+HOl48adKZznncbWJmVQmJmDyJw=; h=Cc:Date:From:Reply-To:Subject:To; b=mw4Ix+WiG4cf/q+JcXQMy6EitJhhf9pIusnGl1VUCcNq4IC7/R4kA8RrVmdcBVpRPv0 5uu55GwUdLkRZdvj3F+iJVRyl+cgn/e/S9LBtXt9i1uM3QWE41aIEz8lGl3MkSpA4cjNQ CkgRuSD1EhENLeghDkjWSSznnYT8PXSTkpA= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1651255518865100005 Content-Type: text/plain; charset="utf-8" REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2594 Add EncryptionVariableLib.h for providing encryption and decryption services for protected variables. Add ProtectedVariableLib.h for providing integrity or variables. Cc: Jian J Wang Cc: Liming Gao Cc: Nishant C Mistry Signed-off-by: Jian J Wang Signed-off-by: Nishant C Mistry Signed-off-by: Judah Vang --- MdeModulePkg/Include/Library/EncryptionVariableLib.h | 165 +++++ MdeModulePkg/Include/Library/ProtectedVariableLib.h | 700 +++++++++++++++= +++++ 2 files changed, 865 insertions(+) diff --git a/MdeModulePkg/Include/Library/EncryptionVariableLib.h b/MdeModu= lePkg/Include/Library/EncryptionVariableLib.h new file mode 100644 index 000000000000..c7740e659dcf --- /dev/null +++ b/MdeModulePkg/Include/Library/EncryptionVariableLib.h @@ -0,0 +1,165 @@ +/** @file + Provides services to encrypt/decrypt variables. + +Copyright (c) 2022, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef ENCRYPTION_VARIABLE_LIB_H_ +#define ENCRYPTION_VARIABLE_LIB_H_ + +#include + +#include + +#include + +#define ENC_TYPE_NULL 0 +#define ENC_TYPE_AES TPM_ALG_AES + +typedef struct _VARIABLE_ENCRYPTION_FLAGS { + BOOLEAN Auth; // Variable is authenticated or not + BOOLEAN DecryptInPlace; // Do decryption in place + BOOLEAN Protected; // Variable is protected or not +} VARIABLE_ENCRYPTION_FLAGS; + +typedef struct _VARIABLE_ENCRYPTION_INFO { + AUTH_VARIABLE_INFO Header; // Authenticated varabil= e header + VARIABLE_HEADER *Buffer; // Pointer to variable b= uffer + UINT64 StoreIndex; // Variable store index + VOID *PlainData; // Pointer to plain data + UINT32 PlainDataSize; // Size of plain data + VOID *CipherData; // Pointer to cipher data + UINT32 CipherDataSize; // Size of cipher data + UINT32 CipherHeaderSize; // Size of cipher header + UINT32 CipherDataType; // Type of cipher data + VOID *Key; // Pointer to encrypt/de= crypt key + UINT32 KeySize; // Size of key + VARIABLE_ENCRYPTION_FLAGS Flags; // Encryption flags +} VARIABLE_ENCRYPTION_INFO; + +/** + Encrypt variable data. + + @param[in, out] VarInfo Pointer to structure containing detailed inf= ormation about a variable. + + @retval EFI_SUCCESS Function successfully executed. + @retval EFI_INVALID_PARAMETER If ProtectedVarLibContextIn =3D=3D NUL= L or ProtectedVarLibContextOut =3D=3D NULL. + @retval EFI_OUT_OF_RESOURCES Fail to allocate enough resource. + @retval EFI_UNSUPPORTED Unsupported to process authenticated v= ariable. + +**/ +EFI_STATUS +EFIAPI +EncryptVariable ( + IN OUT VARIABLE_ENCRYPTION_INFO *VarInfo + ); + +/** + Decrypt variable data. + + If VarEncInfo->CipherData is not NULL, it must holds the cipher data to = be + decrypted. Otherwise, assume the cipher data from variable data buffer, = i.e. + VarEncInfo->Header.Data. + + If VarEncInfo->Flags.DecryptInPlace is TRUE, the decrypted data will be = put + back in the same buffer as cipher buffer got above, after encryption hea= der, + which helps to identify later if the data in buffer is decrypted or not.= This + can avoid repeat decryption when accessing the same variable more than o= nce. + + If VarEncInfo->Flags.DecryptInPlace is FALSE, VarEncInfo->PlainData must= be + passed in with a valid buffer with VarEncInfo->PlainDataSize set correct= ly + with its size. + + Note the VarEncInfo->PlainData is always pointing to the buffer address = with + decrypted data without encryption header, and VarEncInfo->PlainDataSize = is + always the size of original variable data, if this function returned + successfully. + + @param[in, out] VarInfo Pointer to structure containing detailed + information about a variable. + + @retval EFI_SUCCESS Variable was decrypted successfully. + @retval EFI_INVALID_PARAMETER Variable information in VarEncInfo is in= valid. + @retval EFI_BUFFER_TOO_SMALL VarEncInfo->PlainData is not NULL but + VarEncInfo->PlainDataSize is too small. + @retval EFI_ABORTED Uknown error occurred during decrypting. + @retval EFI_OUT_OF_RESOURCES Fail to allocate enough resource. + @retval EFI_COMPROMISED_DATA The cipher header is not valid. + @retval EFI_UNSUPPORTED Unsupported to encrypt variable. + +**/ +EFI_STATUS +EFIAPI +DecryptVariable ( + IN OUT VARIABLE_ENCRYPTION_INFO *VarInfo + ); + +/** + Get cipher information about a variable, including plaindata size, + cipher algorithm type, etc. + + For data passed in with VarEncInfo, + + VarEncInfo->Header.Data + - The variable data in normal variable structure. + VarEncInfo->Header.DataSize + - The size of variable data. + + For data passed out with VarEncInfo (valid only if EFI_SUCCESS is return= ed), + + VarEncInfo->CipherDataType + - ENC_TYPE_NULL, if the variable is not encrypted or has been decryp= ted; + - ENC_TYPE_AES, if the variable is encrypted. + VarEncInfo->CipherHeaderSize + - Size of cipher header put before encrypted or decrypted data. + VarEncInfo->PlainData + - NULL, if the variable is encrypted; Or + - pointer to original variable data, if the variable has been decryp= ted. + VarEncInfo->PlainDataSize + - The size of original variable data + VarEncInfo->CipherData + - NULL, if the variable is decrypted; Or + - pointer to start of encrypted variable data, including encryption = header; + VarEncInfo->CipherDataSize + - The size of encrypted variable data, including encryption header. + + @param[in, out] VarInfo Pointer to structure containing detailed + information about a variable. + + @retval EFI_SUCCESS The information was retrieved successful= ly. + @retval EFI_INVALID_PARAMETER Variable information in VarEncInfo is in= valid. + @retval EFI_NOT_FOUND No cipher information recognized. + @retval EFI_UNSUPPORTED Unsupported interface. + +**/ +EFI_STATUS +EFIAPI +GetCipherDataInfo ( + IN OUT VARIABLE_ENCRYPTION_INFO *VarInfo + ); + +/** + Force set cipher information for a variable, like plaindata size, + cipher algorithm type, cipher data etc. + + The destination buffer must be passed via VarEncInfo->Header.Data. + + This method is only used to update and/or change plain data information. + + @param[in, out] VarInfo Pointer to structure containing detailed + information about a variable. + + @retval EFI_SUCCESS The information was updated successfully. + @retval EFI_INVALID_PARAMETER Variable information in VarEncInfo is in= valid. + @retval EFI_UNSUPPORTED If this method is not supported. + +**/ +EFI_STATUS +EFIAPI +SetCipherDataInfo ( + IN OUT VARIABLE_ENCRYPTION_INFO *VarInfo + ); + +#endif //_ENCRYPTION_VARIABLE_LIB_H_ diff --git a/MdeModulePkg/Include/Library/ProtectedVariableLib.h b/MdeModul= ePkg/Include/Library/ProtectedVariableLib.h new file mode 100644 index 000000000000..2f57b4ebbc70 --- /dev/null +++ b/MdeModulePkg/Include/Library/ProtectedVariableLib.h @@ -0,0 +1,700 @@ +/** @file + Defines interfaces of protected variable services for non-volatile varia= ble + storage. + +Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef PROTECTED_VARIABLE_LIB_H_ +#define PROTECTED_VARIABLE_LIB_H_ + +#include +#include + +#include + +#include +#include + +#include +#include + +#pragma pack(1) + +typedef struct _VARIABLE_DIGEST_FLAGS { + BOOLEAN Auth; // Authenticated variable for= mat + BOOLEAN Valid; // Valid variable data in cur= rent variable + BOOLEAN Protected; // Protected variable (used i= n calculating HMAC) + BOOLEAN Encrypted; // Encrypted variable + BOOLEAN Freeable; // Memory reserved for curren= t node can be freed + BOOLEAN CacheIndexAhead; // Indicates if CacheIndex is= Ahead relative to Global structure + BOOLEAN Reserved[2]; // Reserved fields +} VARIABLE_DIGEST_FLAGS; + +typedef struct _VARIABLE_DIGEST { + /// + /// Pointer to digest of next variable in a pre-defined rule of order for + /// integration verification. In other words, the final HMAC of all + /// protected variables is calculated by concatenating digest of each + /// variable in the order of this singly linked list. + /// + EFI_PHYSICAL_ADDRESS Prev; + EFI_PHYSICAL_ADDRESS Next; + /// + /// Index to variable in physical store, used to locate the variable dir= ectly + /// inside the store (Implementation dependent). + /// + EFI_PHYSICAL_ADDRESS StoreIndex; + /// + /// Index to variable in memory cache, used to locate the variable direc= tly + /// inside the cache (Implementation dependent). + /// + EFI_PHYSICAL_ADDRESS CacheIndex; + + /// + /// Pointer to Cache offset within Global Structure + /// + UINT32 CacheOffset; + + /// + /// Frequently accessed information relating to the variable. + /// + UINT16 DigestSize; // Size of digest value + UINT16 NameSize; // Size of variable name + UINT32 DataSize; // Size of variable data + UINT32 PlainDataSize; // Size of plain data of current= variable (if encrypted) + UINT32 State; // State of current variable + UINT32 Attributes; // Attributes of current variable + + EFI_GUID VendorGuid; // GUID + VARIABLE_DIGEST_FLAGS Flags; // Variable digest flags + // + // Data with variable length are put at the end of this structure. + // + // CHAR16 VariableName[NameSize/2]; + // UINT8 DigestValue[DigestSize]; +} VARIABLE_DIGEST; + +#pragma pack() + +#define VAR_DIG_NAMEOFF(VarDig) (sizeof (VARIABLE_DIGEST)) +#define VAR_DIG_DIGOFF(VarDig) (VAR_DIG_NAMEOFF (VarDig) + (VarDig)->Nam= eSize) + +#define VAR_DIG_END(VarDig) (VAR_DIG_DIGOFF (VarDig) + (VarDig)->DigestSi= ze) + +#define VAR_DIG_VALUE(VarDig) (VOID *)((UINTN)(VarDig) + VAR_DIG_DIGOFF (= VarDig)) +#define VAR_DIG_NAME(VarDig) (CHAR16 *)((UINTN)(VarDig) + VAR_DIG_NAMEOF= F (VarDig)) +#define VAR_DIG_GUID(VarDig) &(VAR_DIG_PTR (VarDig)->VendorGuid) + +#define VAR_DIG_PTR(Addr) ((VARIABLE_DIGEST *)(UINTN)(Addr)) +#define VAR_DIG_ADR(Ptr) ((EFI_PHYSICAL_ADDRESS)(UINTN)(Ptr)) +#define VAR_DIG_NEXT(VarDig) (VAR_DIG_PTR ((VarDig)->Next)) +#define VAR_DIG_PREV(VarDig) (VAR_DIG_PTR ((VarDig)->Prev)) + +#define VAR_INDEX_INVALID ((UINT64)(-1)) + +#define VAR_HDR_PTR(Addr) ((VARIABLE_HEADER *)(UINTN)(Addr)) + +typedef VARIABLE_ENCRYPTION_INFO PROTECTED_VARIABLE_INFO; + +/** + + This function writes data to the NV variable storage at given position. + + Note: Per current variable service architecture, only SMM is allowed to + (directly) change NV variable storage. + + @param VariableInfo Pointer to structure holding details of = a variable. + @param Offset Offset to the given variable to write fr= om. + @param Size Size of data to be written. + @param Buffer Pointer to the buffer from which data is= written. + + @retval EFI_INVALID_PARAMETER Invalid parameters passed in. + @retval EFI_UNSUPPORTED Updating NV variable storage is not suppo= rted. + @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the opera= tion. + @retval EFI_SUCCESS Variable store successfully updated. + +**/ +typedef +EFI_STATUS +(EFIAPI *PROTECTED_VAR_LIB_UPDATE_VARIABLE_STORE)( + IN PROTECTED_VARIABLE_INFO *VariableInfo, + IN UINTN Offset, + IN UINT32 Size, + IN UINT8 *Buffer + ); + +/** + Update the variable region with Variable information. + + @param[in] AuthVariableInfo Pointer AUTH_VARIABLE_INFO structure f= or + input of the variable. + + @retval EFI_SUCCESS The update operation is success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_WRITE_PROTECTED Variable is write-protected. + @retval EFI_OUT_OF_RESOURCES There is not enough resource. + +**/ +typedef +EFI_STATUS +(EFIAPI *PROTECTED_VAR_LIB_UPDATE_VARIABLE)( + IN AUTH_VARIABLE_INFO *AuthVariableInfo + ); + +/** + + Retrieve details about a variable and return them in VariableInfo->Heade= r. + + If VariableInfo->Address is given, this function will calculate its offs= et + relative to given variable storage via VariableStore; Otherwise, it will= try + other internal variable storages or cached copies. It's assumed that, fo= r all + copies of NV variable storage, all variables are stored in the same rela= tive + position. If VariableInfo->Address is found in the range of any storage = copies, + its offset relative to that storage should be the same in other copies. + + If VariableInfo->Offset is given (non-zero) but not VariableInfo->Addres= s, + this function will return the variable memory address inside VariableSto= re, + if given, via VariableInfo->Address; Otherwise, the address of other sto= rage + copies will be returned, if any. + + For a new variable whose offset has not been determined, a value of -1 as + VariableInfo->Offset should be passed to skip the offset calculation. + + @param VariableInfo Pointer to variable information. + + @retval EFI_INVALID_PARAMETER VariableInfo is NULL or both VariableInfo= ->Address + and VariableInfo->Offset are NULL (0). + @retval EFI_NOT_FOUND If given Address or Offset is out of rang= e of + any given or internal storage copies. + @retval EFI_SUCCESS Variable details are retrieved successful= ly. + +**/ +typedef +EFI_STATUS +(EFIAPI *PROTECTED_VAR_LIB_GET_VAR_INFO)( + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo + ); + +/** + + Retrieve details of the variable next to given variable within VariableS= tore. + + If VarInfo->Address is NULL, the first one in VariableStore is returned. + + VariableStart and/or VariableEnd can be given optionally for the situati= on + in which the valid storage space is smaller than the VariableStore->Size. + This usually happens when PEI variable services make a compact variable + cache to save memory, which cannot make use VariableStore->Size to deter= mine + the correct variable storage range. + + @param VariableStore Pointer to a variable storage. It's opti= onal. + @param VariableStart Start point of valid range in VariableSt= ore. + @param VariableEnd End point of valid range in VariableStor= e. + @param VariableInfo Pointer to variable information. + + @retval EFI_INVALID_PARAMETER VariableInfo or VariableStore is NULL. + @retval EFI_NOT_FOUND If the end of VariableStore is reached. + @retval EFI_SUCCESS The next variable is retrieved successful= ly. + +**/ +typedef +EFI_STATUS +(EFIAPI *PROTECTED_VAR_LIB_GET_NEXT_VAR_INFO)( + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo + ); + +typedef +EFI_STATUS +(EFIAPI *DIGEST_METHOD_CALLBACK)( + IN VARIABLE_HEADER *Variable, + IN OUT VARIABLE_DIGEST *Digest + ); + +/** + + Initialize a memory copy of NV variable storage. + + To save memory consumption (especially in PEI phase), it's allowed to ca= che + only valid variables. In such case, an index table recording offset of e= ach + valid variables could be employed. The index table makes sure the cached= copy + to be synchronized with the original copy in NV variable storage. To avo= id + TOCTOU issue, once the variables are cached in memory and verified, NV + variable storage should not be used to read variable information. The ca= ched + copy should be used instead. + + If StoreCacheBase is not given, this function should return the required + cache size and valid variable number, if VariableNumber is not NULL. Then + the caller can prepare correct cache buffer and index table buffer before + next calling. + + @param[in] CacheBase Base address of NV variable storage cach= e. + @param[in] CacheSize Size of CacheBuffer. + @param[out] CacheSize Size of required cache buffer. + @param[out] DigBuffer Base address of digest of each variable. + @param[in, out] DigBufferSize Digest size of one variable if DigestBuf= fer is NULL. + Size of DigestBuffer if DigestBuffer is = NOT NULL. + @param[out] DigSize Required size of DigestBuffer if DigestB= uffer is NULL. + @param[out] DigMethod Method used to generate digest for each = variable. + @param[out] VarNumber Number of valid variables. + @param[out] AuthFlag Auth-variable indicator. + + @retval EFI_INVALID_PARAMETER CacheSize is NULL; Or, + StoreCacheBase is 0 but *CacheSize it no= t. + @retval EFI_VOLUME_CORRUPTED If original NV variable storage is corru= pted. + @retval EFI_BUFFER_TOO_SMALL If *CacheSize is smaller than required m= emory. + @retval EFI_SUCCESS The cached variable storage is initializ= ed. + +**/ +typedef +EFI_STATUS +(EFIAPI *PROTECTED_VAR_LIB_INIT_VAR_STORE)( + OUT VOID *CacheBase OPTIONAL, + IN OUT UINT32 *CacheSize OPTIONAL, + OUT VOID *DigBuffer OPTIONAL, + IN OUT UINT32 *DigBufferSize OPTIONAL, + IN UINT32 DigSize OPTIONAL, + IN DIGEST_METHOD_CALLBACK DigMethod OPTIONAL, + OUT UINT32 *VarNumber OPTIONAL, + OUT BOOLEAN *AuthFlag OPTIONAL + ); + +/** + + Initiate a variable retrieval in SMM environment from non-SMM environmen= t. + + This is usually required in BS/RT environment when local cached copy is = in + encrypted form. Variable decryption can only be done in SMM environment. + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[out] Attributes Attribute value of the variable found. + @param[in, out] DataSize Size of Data found. If size is less t= han the + data, this value contains the require= d size. + @param[out] Data Data pointer. + + @retval EFI_SUCCESS Found the specified variable. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND The specified variable could not be f= ound. + +**/ +typedef +EFI_STATUS +(EFIAPI *PROTECTED_VAR_LIB_FIND_VAR_SMM)( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ); + +/** + Check if a variable is user variable or not. + + @param[in] Variable Pointer to variable header. + + @retval TRUE User variable. + @retval FALSE System variable. + +**/ +typedef +BOOLEAN +(EFIAPI *PROTECTED_VAR_LIB_IS_USER_VAR)( + IN VARIABLE_HEADER *Variable + ); + +/** + Check if a HOB variable store is available or not. + + @retval EFI_NOT_READY HOB variable store info not available. + @retval EFI_NOT_FOUND HOB variable store is NOT available. + @retval EFI_SUCCESS HOB variable store is available. +**/ +typedef +EFI_STATUS +(EFIAPI *PROTECTED_VAR_LIB_HOB_STORE_AVAILABLE)( + VOID + ); + +typedef enum { + FromPeiModule, + FromBootServiceModule, + FromRuntimeModule, + FromSmmModule +} VARIABLE_SERVICE_USER; + +#pragma pack(1) + +#define PROTECTED_VARIABLE_CONTEXT_IN_STRUCT_VERSION 0x02 + +typedef struct _PROTECTED_VARIABLE_CONTEXT_IN { + UINT32 StructVersion; + UINT32 StructSize; + UINT32 MaxVariableSize; + + VARIABLE_SERVICE_USER VariableServiceUser; + + PROTECTED_VAR_LIB_FIND_VAR_SMM FindVariableSmm; + PROTECTED_VAR_LIB_GET_VAR_INFO GetVariableInfo; + PROTECTED_VAR_LIB_GET_NEXT_VAR_INFO GetNextVariableInfo; + PROTECTED_VAR_LIB_UPDATE_VARIABLE_STORE UpdateVariableStore; + PROTECTED_VAR_LIB_UPDATE_VARIABLE UpdateVariable; + PROTECTED_VAR_LIB_HOB_STORE_AVAILABLE IsHobVariableStoreAvailable; +} PROTECTED_VARIABLE_CONTEXT_IN; + +#pragma pack() + +/** + + Initialization for protected variable services. + + If this initialization failed upon any error, the whole variable services + should not be used. A system reset might be needed to re-construct NV + variable storage to be the default state. + + @param[in] ContextIn Pointer to variable service context needed by + protected variable. + + @retval EFI_SUCCESS Protected variable services are ready. + @retval EFI_INVALID_PARAMETER If ContextIn =3D=3D NULL or something = missing or + mismatching in the content in ContextI= n. + @retval EFI_COMPROMISED_DATA If failed to check integrity of protec= ted variables. + @retval EFI_OUT_OF_RESOURCES Fail to allocate enough resource. + @retval EFI_UNSUPPORTED Unsupported to process protected varia= ble. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibInitialize ( + IN PROTECTED_VARIABLE_CONTEXT_IN *ContextIn + ); + +/** + + An alternative version of ProtectedVariableLibGetData to get plain data,= if + encrypted, from given variable, for different use cases. + + @param[in,out] VarInfo Pointer to structure containing variable= information. + + @retval EFI_SUCCESS Found the specified variable. + @retval EFI_INVALID_PARAMETER VarInfo is NULL or both VarInfo->Addre= ss and + VarInfo->Offset are invalid. + @retval EFI_NOT_FOUND The specified variable could not be fo= und. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibGetByInfo ( + IN OUT PROTECTED_VARIABLE_INFO *VarInfo + ); + +/** + This service retrieves a variable's value using its name and GUID. + + Read the specified variable from the UEFI variable store. If the Data + buffer is too small to hold the contents of the variable, the error + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buf= fer + size to obtain the data. + + @param VariableName A pointer to a null-terminated string that= is the variable's name. + @param VariableGuid A pointer to an EFI_GUID that is the varia= ble's GUID. The combination of + VariableGuid and VariableName must be uniq= ue. + @param Attributes If non-NULL, on return, points to the vari= able's attributes. + @param DataSize On entry, points to the size in bytes of t= he Data buffer. + On return, points to the size of the data = returned in Data. + @param Data Points to the buffer which will hold the r= eturned variable value. + May be NULL with a zero DataSize in order = to determine the size of the buffer needed. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable was be found. + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resultin= g data. + DataSize is updated with the size required= for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Da= ta is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved becaus= e of a device error. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibGetByName ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ); + +/** + + Retrieve plain data, if encrypted, of given variable. + + If variable encryption is employed, this function will initiate a SMM re= quest + to get the plain data. Due to security consideration, the decryption can= only + be done in SMM environment. + + @param[in] Variable Pointer to header of a Variable. + @param[out] Data Pointer to plain data of the given va= riable. + @param[in, out] DataSize Size of data returned or data buffer = needed. + @param[in] AuthFlag Auth-variable indicator. + + @retval EFI_SUCCESS Found the specified variable. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND The specified variable could not be f= ound. + @retval EFI_BUFFER_TOO_SMALL If *DataSize is smaller than needed. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibGetByBuffer ( + IN VARIABLE_HEADER *Variable, + IN OUT VOID *Data, + IN OUT UINT32 *DataSize, + IN BOOLEAN AuthFlag + ); + +/** + + Prepare for variable update. + + This is needed only once during current boot to mitigate replay attack. = Its + major job is to advance RPMC (Replay Protected Monotonic Counter). + + @retval EFI_SUCCESS Variable is ready to update hereafter. + @retval EFI_UNSUPPORTED Updating variable is not supported. + @retval EFI_DEVICE_ERROR Error in advancing RPMC. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibWriteInit ( + VOID + ); + +/** + + Update a variable with protection provided by this library. + + If variable encryption is employed, the new variable data will be encryp= ted + before being written to NV variable storage. + + A special variable, called "MetaDataHmacVar", will always be updated alo= ng + with variable being updated to reflect the changes (HMAC value) of all + protected valid variables. The only exceptions, currently, are variable + "MetaDataHmacVar" itself and variable "VarErrorLog". + + The buffer passed by NewVariable must be double of maximum variable size, + which allows to pass the "MetaDataHmacVar" back to caller along with enc= rypted + new variable data, if any. This can make sure the new variable data and + "MetaDataHmacVar" can be written at almost the same time to reduce the c= hance + of compromising the integrity. + + If *NewVariableSize is zero, it means to delete variable passed by CurrV= ariable + and/or CurrVariableInDel. "MetaDataHmacVar" will be updated as well in s= uch + case because of less variables in storage. NewVariable should be always = passed + in to convey new "MetaDataHmacVar" back. + + @param[in,out] CurrVariable Variable to be updated. It's NULL if + adding a new variable. + @param[in,out] CurrVariableInDel In-delete-transition copy of updatin= g variable. + @param[in] NewVariable Buffer of new variable data. + @param[out] NewVariable Buffer of "MetaDataHmacVar" and new + variable (encrypted). + @param[in] NewVariableSize Size of NewVariable. + @param[out] NewVariableSize Size of (encrypted) NewVariable and + "MetaDataHmacVar". + + @retval EFI_SUCCESS The variable is updated with protection = successfully. + @retval EFI_INVALID_PARAMETER NewVariable is NULL. + @retval EFI_NOT_FOUND Information missing to finish the operat= ion. + @retval EFI_ABORTED Failed to encrypt variable or calculate = HMAC. + @retval EFI_NOT_READY The RPMC device is not yet initialized. + @retval EFI_DEVICE_ERROR The RPMC device has error in updating. + @retval EFI_ACCESS_DENIED The given variable is not allowed to upd= ate. + Currently this only happens on updating + "MetaDataHmacVar" from code outside of t= his + library. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibUpdate ( + IN OUT VARIABLE_HEADER *CurrVariable OPTIONAL, + IN OUT VARIABLE_HEADER *CurrVariableInDel OPTIONAL, + IN OUT VARIABLE_HEADER *NewVariable, + IN OUT UINTN *NewVariableSize + ); + +/** + + Finalize a variable updating after it's written to NV variable storage + successfully. + + This usually includes works like increasing RPMC, synchronizing local ca= che, + updating new position of "MetaDataHmacVar", deleting old copy of "MetaDa= taHmacVar" + completely, etc. + + @param[in] NewVariable Buffer of new variables and MetaDataHm= acVar. + @param[in] VariableSize Size of buffer pointed by NewVariable. + @param[in] Offset Offset to NV variable storage from whe= re the new + variable and MetaDataHmacVar have been= written. + + @retval EFI_SUCCESS No problem in winding up the variable write = operation. + @retval Others Failed to updating state of old copy of upda= ted + variable, or failed to increase RPMC, etc. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibWriteFinal ( + IN VARIABLE_HEADER *NewVariable, + IN UINTN VariableSize, + IN UINT64 StoreIndex + ); + +/** + Return the request variable name and GUID as per StoreIndex. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param This A pointer to this instance of the EFI_PEI_READ= _ONLY_VARIABLE2_PPI. + + @param VariableNameSize On entry, points to the size of the buffer poi= nted to by VariableName. + On return, the size of the variable name buffe= r. + @param VariableName On entry, a pointer to a null-terminated strin= g that is the variable's name. + On return, points to the next variable's null-= terminated name string. + @param VariableGuid On entry, a pointer to an EFI_GUID that is the= variable's GUID. + On return, a pointer to the next variable's GU= ID. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the = resulting + data. VariableNameSize is updated with the= size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved becaus= e of a device error. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibFind ( + IN OUT PROTECTED_VARIABLE_INFO *VarInfo + ); + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param VariableNameSize On entry, points to the size of the buffer poi= nted to by VariableName. + On return, the size of the variable name buffe= r. + @param VariableName On entry, a pointer to a null-terminated strin= g that is the variable's name. + On return, points to the next variable's null-= terminated name string. + @param VariableGuid On entry, a pointer to an EFI_GUID that is the= variable's GUID. + On return, a pointer to the next variable's GU= ID. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the = resulting + data. VariableNameSize is updated with the= size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved becaus= e of a device error. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibFindNext ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid + ); + +/** + Find variable via information in data structure PROTECTED_VARIABLE_INFO. + + If VarInfo->StoreIndex is given and valid, always used it to search var= iable + in store. Otherwise, search the variable via variable name and guid poi= nted + by VarInfo->Header.VariableName and VarInfo->Header.VendorGuid. + + @param VarInfo Pointer to data containing variable information. + + @return EFI_SUCCESS Found the variable. + @return EFI_INVALID_PARAMETER No valid variable information is given. + @return EFI_NOT_FOUND The given variable was not found or no more + variables available. +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibFindNextEx ( + IN OUT PROTECTED_VARIABLE_INFO *VarInfo + ); + +/** + Refresh variable information changed by variable service. + + @param Variable Pointer to buffer of the updated variable. + @param VariableSize Size of variable pointed by Variable. + @param StoreIndex New index of the variable in store. + @param RefreshData Flag to indicate if the variable has been update= d. + + @return EFI_SUCCESS No error occurred in updating. + @return EFI_NOT_FOUND The given variable was not found in + ProtectedVariableLib. +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibRefresh ( + IN VARIABLE_HEADER *Variable, + IN UINTN VariableSize, + IN UINT64 StoreIndex, + IN BOOLEAN RefreshData + ); + +/** + Refresh variable information changed by variable service. + + @param Buffer Pointer to a pointer of buffer. + @param NumElements Pointer to number of elements in list. + + + @return EFI_SUCCESS Successfully retrieved sorted list. + @return others Unsuccessful. + +**/ +EFI_STATUS +EFIAPI +ProtectedVariableLibGetSortedList ( + IN OUT EFI_PHYSICAL_ADDRESS **Buffer, + IN OUT UINTN *NumElements + ); + +/** + + Determine if the variable is the HMAC variable + + @param VariableName Pointer to variable name. + + @return TRUE Variable is HMAC variable + @return FALSE Variable is not HMAC variable + +**/ +BOOLEAN +ProtectedVariableLibIsHmac ( + IN CHAR16 *VariableName + ); + +#endif --=20 2.35.1.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#89424): https://edk2.groups.io/g/devel/message/89424 Mute This Topic: https://groups.io/mt/90781891/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-