From: "Wu, Hao A" <hao.a.wu@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
"Vang, Judah" <judah.vang@intel.com>
Cc: "Wang, Jian J" <jian.j.wang@intel.com>,
"Gao, Liming" <gaoliming@byosoft.com.cn>,
"Mistry, Nishant C" <nishant.c.mistry@intel.com>
Subject: Re: [edk2-devel] [PATCH v3 06/28] MdeModulePkg: Add new include files
Date: Mon, 13 Jun 2022 06:07:40 +0000 [thread overview]
Message-ID: <DM6PR11MB4025E2DBE3473BBE17FC4776CAAB9@DM6PR11MB4025.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20220609060322.3491-7-judah.vang@intel.com>
Please refer to inline comment below (tagged as "[Hao]"):
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Judah Vang
> Sent: Thursday, June 9, 2022 2:03 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Mistry, Nishant C <nishant.c.mistry@intel.com>
> Subject: [edk2-devel] [PATCH v3 06/28] MdeModulePkg: Add new include files
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2594
>
> Add EncryptionVariableLib.h for providing encryption and
> decryption services for protected variables.
> Add ProtectedVariableLib.h for providing integrity or
> variables.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Nishant C Mistry <nishant.c.mistry@intel.com>
> Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
> Signed-off-by: Nishant C Mistry <nishant.c.mistry@intel.com>
> Signed-off-by: Judah Vang <judah.vang@intel.com>
> ---
> 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/MdeModulePkg/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.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef ENCRYPTION_VARIABLE_LIB_H_
> +#define ENCRYPTION_VARIABLE_LIB_H_
> +
> +#include <IndustryStandard/Tpm20.h>
> +
> +#include <Guid/VariableFormat.h>
> +
> +#include <Library/AuthVariableLib.h>
> +
> +#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 varabile header
> + VARIABLE_HEADER *Buffer; // Pointer to variable buffer
> + 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/decrypt 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
> information about a variable.
> +
> + @retval EFI_SUCCESS Function successfully executed.
> + @retval EFI_INVALID_PARAMETER If ProtectedVarLibContextIn == NULL or
> ProtectedVarLibContextOut == NULL.
> + @retval EFI_OUT_OF_RESOURCES Fail to allocate enough resource.
> + @retval EFI_UNSUPPORTED Unsupported to process authenticated
> variable.
> +
> +**/
> +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 header,
> + 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
> once.
> +
> + If VarEncInfo->Flags.DecryptInPlace is FALSE, VarEncInfo->PlainData must be
> + passed in with a valid buffer with VarEncInfo->PlainDataSize set correctly
> + 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
> invalid.
> + @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 returned),
> +
> + VarEncInfo->CipherDataType
> + - ENC_TYPE_NULL, if the variable is not encrypted or has been decrypted;
> + - 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 decrypted.
> + 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 successfully.
> + @retval EFI_INVALID_PARAMETER Variable information in VarEncInfo is
> invalid.
> + @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
> invalid.
> + @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/MdeModulePkg/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 variable
> + storage.
> +
> +Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef PROTECTED_VARIABLE_LIB_H_
> +#define PROTECTED_VARIABLE_LIB_H_
> +
> +#include <PiPei.h>
> +#include <PiDxe.h>
> +
> +#include <Guid/VariableFormat.h>
> +
> +#include <Protocol/VarCheck.h>
> +#include <Protocol/FirmwareVolumeBlock.h>
> +
> +#include <Library/UefiLib.h>
> +#include <Library/EncryptionVariableLib.h>
> +
> +#pragma pack(1)
> +
> +typedef struct _VARIABLE_DIGEST_FLAGS {
> + BOOLEAN Auth; // Authenticated variable format
> + BOOLEAN Valid; // Valid variable data in current variable
> + BOOLEAN Protected; // Protected variable (used in calculating
> HMAC)
> + BOOLEAN Encrypted; // Encrypted variable
> + BOOLEAN Freeable; // Memory reserved for current 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 directly
> + /// inside the store (Implementation dependent).
> + ///
> + EFI_PHYSICAL_ADDRESS StoreIndex;
> + ///
> + /// Index to variable in memory cache, used to locate the variable directly
> + /// 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)-
> >NameSize)
> +
> +#define VAR_DIG_END(VarDig) (VAR_DIG_DIGOFF (VarDig) + (VarDig)-
> >DigestSize)
> +
> +#define VAR_DIG_VALUE(VarDig) (VOID *)((UINTN)(VarDig) +
> VAR_DIG_DIGOFF (VarDig))
> +#define VAR_DIG_NAME(VarDig) (CHAR16 *)((UINTN)(VarDig) +
> VAR_DIG_NAMEOFF (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 from.
> + @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
> supported.
> + @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the
> operation.
> + @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 for
> + 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->Header.
> +
> + If VariableInfo->Address is given, this function will calculate its offset
> + relative to given variable storage via VariableStore; Otherwise, it will try
> + other internal variable storages or cached copies. It's assumed that, for all
> + copies of NV variable storage, all variables are stored in the same relative
> + 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->Address,
> + this function will return the variable memory address inside VariableStore,
> + if given, via VariableInfo->Address; Otherwise, the address of other storage
> + 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 range of
> + any given or internal storage copies.
> + @retval EFI_SUCCESS Variable details are retrieved successfully.
[Hao]: For the above description:
"VariableInfo->Index" -> "VariableInfo->StoreIndex"
Best Regards,
Hao Wu
> +
> +**/
> +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 VariableStore.
> +
> + If VarInfo->Address is NULL, the first one in VariableStore is returned.
> +
> + VariableStart and/or VariableEnd can be given optionally for the situation
> + 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
> determine
> + the correct variable storage range.
> +
> + @param VariableStore Pointer to a variable storage. It's optional.
> + @param VariableStart Start point of valid range in VariableStore.
> + @param VariableEnd End point of valid range in VariableStore.
> + @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 successfully.
> +
> +**/
> +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 cache
> + only valid variables. In such case, an index table recording offset of each
> + 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 avoid
> + TOCTOU issue, once the variables are cached in memory and verified, NV
> + variable storage should not be used to read variable information. The cached
> + 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 cache.
> + @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 DigestBuffer is
> NULL.
> + Size of DigestBuffer if DigestBuffer is NOT NULL.
> + @param[out] DigSize Required size of DigestBuffer if DigestBuffer 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 not.
> + @retval EFI_VOLUME_CORRUPTED If original NV variable storage is
> corrupted.
> + @retval EFI_BUFFER_TOO_SMALL If *CacheSize is smaller than required
> memory.
> + @retval EFI_SUCCESS The cached variable storage is initialized.
> +
> +**/
> +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 environment.
> +
> + 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 than the
> + data, this value contains the required 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 found.
> +
> +**/
> +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 == NULL or something
> missing or
> + mismatching in the content in ContextIn.
> + @retval EFI_COMPROMISED_DATA If failed to check integrity of protected
> variables.
> + @retval EFI_OUT_OF_RESOURCES Fail to allocate enough resource.
> + @retval EFI_UNSUPPORTED Unsupported to process protected variable.
> +
> +**/
> +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-
> >Address and
> + VarInfo->Offset are invalid.
> + @retval EFI_NOT_FOUND The specified variable could not be found.
> +
> +**/
> +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 buffer
> + 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 variable's
> GUID. The combination of
> + VariableGuid and VariableName must be unique.
> + @param Attributes If non-NULL, on return, points to the variable's
> attributes.
> + @param DataSize On entry, points to the size in bytes of the Data
> buffer.
> + On return, points to the size of the data returned in Data.
> + @param Data Points to the buffer which will hold the returned
> 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 resulting
> data.
> + DataSize is updated with the size required for
> + the specified variable.
> + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or
> Data is NULL.
> + @retval EFI_DEVICE_ERROR The variable could not be retrieved because 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 request
> + 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 variable.
> + @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 found.
> + @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 encrypted
> + before being written to NV variable storage.
> +
> + A special variable, called "MetaDataHmacVar", will always be updated along
> + 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
> encrypted
> + 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
> chance
> + of compromising the integrity.
> +
> + If *NewVariableSize is zero, it means to delete variable passed by CurrVariable
> + and/or CurrVariableInDel. "MetaDataHmacVar" will be updated as well in such
> + 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 updating
> 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 operation.
> + @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 update.
> + Currently this only happens on updating
> + "MetaDataHmacVar" from code outside of this
> + 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 cache,
> + updating new position of "MetaDataHmacVar", deleting old copy of
> "MetaDataHmacVar"
> + completely, etc.
> +
> + @param[in] NewVariable Buffer of new variables and
> MetaDataHmacVar.
> + @param[in] VariableSize Size of buffer pointed by NewVariable.
> + @param[in] Offset Offset to NV variable storage from where 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 updated
> + 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 pointed
> to by VariableName.
> + On return, the size of the variable name buffer.
> + @param VariableName On entry, a pointer to a null-terminated string 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 GUID.
> +
> + @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 because 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 pointed
> to by VariableName.
> + On return, the size of the variable name buffer.
> + @param VariableName On entry, a pointer to a null-terminated string 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 GUID.
> +
> + @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 because 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 variable
> + in store. Otherwise, search the variable via variable name and guid pointed
> + 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 updated.
> +
> + @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
> --
> 2.35.1.windows.2
>
>
>
>
>
next prev parent reply other threads:[~2022-06-13 6:07 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-09 6:02 [PATCH v3 00/28] UEFI variable protection Judah Vang
2022-06-09 6:02 ` [PATCH v3 01/28] MdeModulePkg: Add new GUID for Variable Store Info Judah Vang
2022-06-13 6:05 ` [edk2-devel] " Wu, Hao A
2022-06-09 6:02 ` [PATCH v3 02/28] SecurityPkg: Add new GUIDs for Judah Vang
2022-06-09 6:02 ` [PATCH v3 03/28] MdeModulePkg: Update AUTH_VARIABLE_INFO struct Judah Vang
2022-06-09 6:02 ` [PATCH v3 04/28] MdeModulePkg: Add reference to new Ppi Guid Judah Vang
2022-06-09 6:02 ` [PATCH v3 05/28] MdeModulePkg: Add new ProtectedVariable GUIDs Judah Vang
2022-06-13 6:07 ` [edk2-devel] " Wu, Hao A
2022-06-09 6:03 ` [PATCH v3 06/28] MdeModulePkg: Add new include files Judah Vang
2022-06-13 6:07 ` Wu, Hao A [this message]
2022-06-09 6:03 ` [PATCH v3 07/28] MdeModulePkg: Add Null ProtectedVariable Library Judah Vang
2022-06-09 6:03 ` [PATCH v3 08/28] MdeModulePkg: Add new Variable functionality Judah Vang
2022-06-13 6:08 ` Wu, Hao A
2022-06-09 6:03 ` [PATCH v3 09/28] MdeModulePkg: Add support for Protected Variables Judah Vang
2022-06-13 6:08 ` Wu, Hao A
2022-06-09 6:03 ` [PATCH v3 10/28] SecurityPkg: Add new KeyService types and defines Judah Vang
2022-06-09 6:03 ` [PATCH v3 11/28] SecurityPkg: Update RPMC APIs with index Judah Vang
2022-06-09 6:03 ` [PATCH v3 12/28] SecurityPkg: Add new variable types and functions Judah Vang
2022-06-09 6:03 ` [PATCH v3 13/28] SecurityPkg: Fix GetVariableKey API Judah Vang
2022-06-09 6:03 ` [PATCH v3 14/28] SecurityPkg: Add null encryption variable libs Judah Vang
2022-06-09 6:03 ` [PATCH v3 15/28] SecurityPkg: Add VariableKey library function Judah Vang
2022-06-09 6:03 ` [PATCH v3 16/28] SecurityPkg: Add EncryptionVariable lib with AES Judah Vang
2022-06-09 6:03 ` [PATCH v3 17/28] SecurityPkg: Add Protected Variable Services Judah Vang
2022-06-09 8:30 ` Min Xu
2022-06-16 19:23 ` [edk2-devel] " Judah Vang
2022-08-07 17:34 ` Wang, Jian J
2022-06-09 6:03 ` [PATCH v3 18/28] MdeModulePkg: Reference Null ProtectedVariableLib Judah Vang
2022-06-13 6:08 ` [edk2-devel] " Wu, Hao A
2022-06-09 6:03 ` [PATCH v3 19/28] SecurityPkg: Add references to new *.inf files Judah Vang
2022-06-09 6:03 ` [PATCH v3 20/28] ArmVirtPkg: Add reference to ProtectedVariableNull Judah Vang
2022-06-09 6:03 ` [PATCH v3 21/28] UefiPayloadPkg: Add ProtectedVariable reference Judah Vang
2022-06-09 6:03 ` [PATCH v3 22/28] EmulatorPkg: " Judah Vang
2022-07-13 5:21 ` [edk2-devel] " Ni, Ray
2022-06-09 6:03 ` [PATCH v3 23/28] OvmfPkg: " Judah Vang
2022-06-09 6:03 ` [PATCH v3 24/28] OvmfPkg: Add ProtectedVariableLib reference Judah Vang
2022-06-09 6:03 ` [PATCH v3 25/28] " Judah Vang
2022-06-09 6:03 ` [PATCH v3 26/28] " Judah Vang
2022-06-09 6:03 ` [PATCH v3 27/28] OvmfPkg: Add ProtectedVariable reference Judah Vang
2022-06-09 6:03 ` [PATCH v3 28/28] CryptoPkg: Enable cypto HMAC KDF and AES library Judah Vang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DM6PR11MB4025E2DBE3473BBE17FC4776CAAB9@DM6PR11MB4025.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox