public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
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
> 
> 
> 
> 
> 


  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