System may break during time based AuthVariable update, causing certdb inconsistent. 2 ways are used to ensure update atomic. 1. Delete cert in certdb after variable is deleted 2. Clean up certdb on variable initialization Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Chao Zhang <chao.b.zhang@intel.com> Reviewed-by: Yao Jiewen <jiewen.yao@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17919 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			428 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			428 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  The internal header file includes the common header files, defines
 | 
						|
  internal structure and functions used by AuthService module.
 | 
						|
 | 
						|
  Caution: This module requires additional review when modified.
 | 
						|
  This driver will have external input - variable data. It may be input in SMM mode.
 | 
						|
  This external input must be validated carefully to avoid security issue like
 | 
						|
  buffer overflow, integer overflow.
 | 
						|
  Variable attribute should also be checked to avoid authentication bypass.
 | 
						|
     The whole SMM authentication variable design relies on the integrity of flash part and SMM.
 | 
						|
  which is assumed to be protected by platform.  All variable code and metadata in flash/SMM Memory
 | 
						|
  may not be modified without authorization. If platform fails to protect these resources,
 | 
						|
  the authentication service provided in this driver will be broken, and the behavior is undefined.
 | 
						|
 | 
						|
Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
 | 
						|
This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#ifndef _AUTHSERVICE_INTERNAL_H_
 | 
						|
#define _AUTHSERVICE_INTERNAL_H_
 | 
						|
 | 
						|
#include <Library/AuthVariableLib.h>
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/BaseCryptLib.h>
 | 
						|
#include <Library/PlatformSecureLib.h>
 | 
						|
 | 
						|
#include <Guid/AuthenticatedVariableFormat.h>
 | 
						|
#include <Guid/ImageAuthentication.h>
 | 
						|
 | 
						|
///
 | 
						|
/// Struct to record signature requirement defined by UEFI spec.
 | 
						|
/// For SigHeaderSize and SigDataSize, ((UINT32) ~0) means NO exact length requirement for this field.
 | 
						|
///
 | 
						|
typedef struct {
 | 
						|
  EFI_GUID    SigType;
 | 
						|
  // Expected SignatureHeader size in Bytes.
 | 
						|
  UINT32      SigHeaderSize;
 | 
						|
  // Expected SignatureData size in Bytes.
 | 
						|
  UINT32      SigDataSize;
 | 
						|
} EFI_SIGNATURE_ITEM;
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  AuthVarTypePk,
 | 
						|
  AuthVarTypeKek,
 | 
						|
  AuthVarTypePriv,
 | 
						|
  AuthVarTypePayload
 | 
						|
} AUTHVAR_TYPE;
 | 
						|
 | 
						|
///
 | 
						|
/// "AuthVarKeyDatabase" variable for the Public Key store
 | 
						|
/// of variables with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
 | 
						|
///
 | 
						|
/// GUID: gEfiAuthenticatedVariableGuid
 | 
						|
///
 | 
						|
/// We need maintain atomicity.
 | 
						|
///
 | 
						|
/// Format:
 | 
						|
/// +----------------------------+
 | 
						|
/// | AUTHVAR_KEY_DB_DATA        | <-- First AuthVarKey
 | 
						|
/// +----------------------------+
 | 
						|
/// | ......                     |
 | 
						|
/// +----------------------------+
 | 
						|
/// | AUTHVAR_KEY_DB_DATA        | <-- Last AuthKey
 | 
						|
/// +----------------------------+
 | 
						|
///
 | 
						|
#define AUTHVAR_KEYDB_NAME      L"AuthVarKeyDatabase"
 | 
						|
 | 
						|
#define EFI_CERT_TYPE_RSA2048_SHA256_SIZE 256
 | 
						|
#define EFI_CERT_TYPE_RSA2048_SIZE        256
 | 
						|
 | 
						|
#pragma pack(1)
 | 
						|
typedef struct {
 | 
						|
  UINT32    KeyIndex;
 | 
						|
  UINT8     KeyData[EFI_CERT_TYPE_RSA2048_SIZE];
 | 
						|
} AUTHVAR_KEY_DB_DATA;
 | 
						|
#pragma pack()
 | 
						|
 | 
						|
///
 | 
						|
/// "certdb" variable stores the signer's certificates for non PK/KEK/DB/DBX
 | 
						|
/// variables with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
 | 
						|
///
 | 
						|
/// GUID: gEfiCertDbGuid
 | 
						|
///
 | 
						|
/// We need maintain atomicity.
 | 
						|
///
 | 
						|
/// Format:
 | 
						|
/// +----------------------------+
 | 
						|
/// | UINT32                     | <-- CertDbListSize, including this UINT32
 | 
						|
/// +----------------------------+
 | 
						|
/// | AUTH_CERT_DB_DATA          | <-- First CERT
 | 
						|
/// +----------------------------+
 | 
						|
/// | ........                   |
 | 
						|
/// +----------------------------+
 | 
						|
/// | AUTH_CERT_DB_DATA          | <-- Last CERT
 | 
						|
/// +----------------------------+
 | 
						|
///
 | 
						|
#define EFI_CERT_DB_NAME        L"certdb"
 | 
						|
 | 
						|
#pragma pack(1)
 | 
						|
typedef struct {
 | 
						|
  EFI_GUID    VendorGuid;
 | 
						|
  UINT32      CertNodeSize;
 | 
						|
  UINT32      NameSize;
 | 
						|
  UINT32      CertDataSize;
 | 
						|
  /// CHAR16  VariableName[NameSize];
 | 
						|
  /// UINT8   CertData[CertDataSize];
 | 
						|
} AUTH_CERT_DB_DATA;
 | 
						|
#pragma pack()
 | 
						|
 | 
						|
extern UINT8    *mPubKeyStore;
 | 
						|
extern UINT32   mPubKeyNumber;
 | 
						|
extern UINT32   mMaxKeyNumber;
 | 
						|
extern UINT32   mMaxKeyDbSize;
 | 
						|
extern UINT8    *mCertDbStore;
 | 
						|
extern UINT32   mMaxCertDbSize;
 | 
						|
extern UINT32   mPlatformMode;
 | 
						|
extern UINT8    mVendorKeyState;
 | 
						|
 | 
						|
extern VOID     *mHashCtx;
 | 
						|
 | 
						|
extern AUTH_VAR_LIB_CONTEXT_IN *mAuthVarLibContextIn;
 | 
						|
 | 
						|
/**
 | 
						|
  Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
  This function may be invoked in SMM mode, and datasize and data are external input.
 | 
						|
  This function will do basic validation, before parse the data.
 | 
						|
  This function will parse the authentication carefully to avoid security issues, like
 | 
						|
  buffer overflow, integer overflow.
 | 
						|
 | 
						|
  @param[in]  VariableName                Name of Variable to be found.
 | 
						|
  @param[in]  VendorGuid                  Variable vendor GUID.
 | 
						|
  @param[in]  Data                        Data pointer.
 | 
						|
  @param[in]  DataSize                    Size of Data found. If size is less than the
 | 
						|
                                          data, this value contains the required size.
 | 
						|
  @param[in]  Attributes                  Attribute value of the variable.
 | 
						|
  @param[in]  AuthVarType                 Verify against PK, KEK database, private database or certificate in data payload.
 | 
						|
  @param[out] VarDel                      Delete the variable or not.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER           Invalid parameter.
 | 
						|
  @retval EFI_SECURITY_VIOLATION          The variable does NOT pass the validation
 | 
						|
                                          check carried out by the firmware.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES            Failed to process variable due to lack
 | 
						|
                                          of resources.
 | 
						|
  @retval EFI_SUCCESS                     Variable pass validation successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
VerifyTimeBasedPayloadAndUpdate (
 | 
						|
  IN     CHAR16                             *VariableName,
 | 
						|
  IN     EFI_GUID                           *VendorGuid,
 | 
						|
  IN     VOID                               *Data,
 | 
						|
  IN     UINTN                              DataSize,
 | 
						|
  IN     UINT32                             Attributes,
 | 
						|
  IN     AUTHVAR_TYPE                       AuthVarType,
 | 
						|
  OUT    BOOLEAN                            *VarDel
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Delete matching signer's certificates when deleting common authenticated
 | 
						|
  variable by corresponding VariableName and VendorGuid from "certdb".
 | 
						|
 | 
						|
  @param[in]  VariableName   Name of authenticated Variable.
 | 
						|
  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.
 | 
						|
 | 
						|
  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.
 | 
						|
  @retval  EFI_NOT_FOUND         Fail to find "certdb" or matching certs.
 | 
						|
  @retval  EFI_OUT_OF_RESOURCES  The operation is failed due to lack of resources.
 | 
						|
  @retval  EFI_SUCCESS           The operation is completed successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DeleteCertsFromDb (
 | 
						|
  IN     CHAR16           *VariableName,
 | 
						|
  IN     EFI_GUID         *VendorGuid
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Clean up signer's certificates for common authenticated variable
 | 
						|
  by corresponding VariableName and VendorGuid from "certdb".
 | 
						|
  Sytem may break down during Timebased Variable update & certdb update,
 | 
						|
  make them inconsistent,  this function is called in AuthVariable Init to ensure 
 | 
						|
  consistency
 | 
						|
  
 | 
						|
  @retval  EFI_NOT_FOUND         Fail to find matching certs.
 | 
						|
  @retval  EFI_SUCCESS           Find matching certs and output parameters.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CleanCertsFromDb (
 | 
						|
  VOID
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Filter out the duplicated EFI_SIGNATURE_DATA from the new data by comparing to the original data.
 | 
						|
 | 
						|
  @param[in]        Data          Pointer to original EFI_SIGNATURE_LIST.
 | 
						|
  @param[in]        DataSize      Size of Data buffer.
 | 
						|
  @param[in, out]   NewData       Pointer to new EFI_SIGNATURE_LIST.
 | 
						|
  @param[in, out]   NewDataSize   Size of NewData buffer.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FilterSignatureList (
 | 
						|
  IN     VOID       *Data,
 | 
						|
  IN     UINTN      DataSize,
 | 
						|
  IN OUT VOID       *NewData,
 | 
						|
  IN OUT UINTN      *NewDataSize
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Process variable with platform key for verification.
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
  This function may be invoked in SMM mode, and datasize and data are external input.
 | 
						|
  This function will do basic validation, before parse the data.
 | 
						|
  This function will parse the authentication carefully to avoid security issues, like
 | 
						|
  buffer overflow, integer overflow.
 | 
						|
  This function will check attribute carefully to avoid authentication bypass.
 | 
						|
 | 
						|
  @param[in]  VariableName                Name of Variable to be found.
 | 
						|
  @param[in]  VendorGuid                  Variable vendor GUID.
 | 
						|
  @param[in]  Data                        Data pointer.
 | 
						|
  @param[in]  DataSize                    Size of Data found. If size is less than the
 | 
						|
                                          data, this value contains the required size.
 | 
						|
  @param[in]  Attributes                  Attribute value of the variable
 | 
						|
  @param[in]  IsPk                        Indicate whether it is to process pk.
 | 
						|
 | 
						|
  @return EFI_INVALID_PARAMETER           Invalid parameter.
 | 
						|
  @return EFI_SECURITY_VIOLATION          The variable does NOT pass the validation.
 | 
						|
                                          check carried out by the firmware.
 | 
						|
  @return EFI_SUCCESS                     Variable passed validation successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ProcessVarWithPk (
 | 
						|
  IN  CHAR16                    *VariableName,
 | 
						|
  IN  EFI_GUID                  *VendorGuid,
 | 
						|
  IN  VOID                      *Data,
 | 
						|
  IN  UINTN                     DataSize,
 | 
						|
  IN  UINT32                    Attributes OPTIONAL,
 | 
						|
  IN  BOOLEAN                   IsPk
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Process variable with key exchange key for verification.
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
  This function may be invoked in SMM mode, and datasize and data are external input.
 | 
						|
  This function will do basic validation, before parse the data.
 | 
						|
  This function will parse the authentication carefully to avoid security issues, like
 | 
						|
  buffer overflow, integer overflow.
 | 
						|
  This function will check attribute carefully to avoid authentication bypass.
 | 
						|
 | 
						|
  @param[in]  VariableName                Name of Variable to be found.
 | 
						|
  @param[in]  VendorGuid                  Variable vendor GUID.
 | 
						|
  @param[in]  Data                        Data pointer.
 | 
						|
  @param[in]  DataSize                    Size of Data found. If size is less than the
 | 
						|
                                          data, this value contains the required size.
 | 
						|
  @param[in]  Attributes                  Attribute value of the variable.
 | 
						|
 | 
						|
  @return EFI_INVALID_PARAMETER           Invalid parameter.
 | 
						|
  @return EFI_SECURITY_VIOLATION          The variable does NOT pass the validation
 | 
						|
                                          check carried out by the firmware.
 | 
						|
  @return EFI_SUCCESS                     Variable pass validation successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ProcessVarWithKek (
 | 
						|
  IN  CHAR16                               *VariableName,
 | 
						|
  IN  EFI_GUID                             *VendorGuid,
 | 
						|
  IN  VOID                                 *Data,
 | 
						|
  IN  UINTN                                DataSize,
 | 
						|
  IN  UINT32                               Attributes OPTIONAL
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
 | 
						|
 | 
						|
  Caution: This function may receive untrusted input.
 | 
						|
  This function may be invoked in SMM mode, and datasize and data are external input.
 | 
						|
  This function will do basic validation, before parse the data.
 | 
						|
  This function will parse the authentication carefully to avoid security issues, like
 | 
						|
  buffer overflow, integer overflow.
 | 
						|
  This function will check attribute carefully to avoid authentication bypass.
 | 
						|
 | 
						|
  @param[in]  VariableName                Name of the variable.
 | 
						|
  @param[in]  VendorGuid                  Variable vendor GUID.
 | 
						|
  @param[in]  Data                        Data pointer.
 | 
						|
  @param[in]  DataSize                    Size of Data.
 | 
						|
  @param[in]  Attributes                  Attribute value of the variable.
 | 
						|
 | 
						|
  @return EFI_INVALID_PARAMETER           Invalid parameter.
 | 
						|
  @return EFI_WRITE_PROTECTED             Variable is write-protected and needs authentication with
 | 
						|
                                          EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
 | 
						|
  @return EFI_OUT_OF_RESOURCES            The Database to save the public key is full.
 | 
						|
  @return EFI_SECURITY_VIOLATION          The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
 | 
						|
                                          set, but the AuthInfo does NOT pass the validation
 | 
						|
                                          check carried out by the firmware.
 | 
						|
  @return EFI_SUCCESS                     Variable is not write-protected or pass validation successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ProcessVariable (
 | 
						|
  IN     CHAR16                             *VariableName,
 | 
						|
  IN     EFI_GUID                           *VendorGuid,
 | 
						|
  IN     VOID                               *Data,
 | 
						|
  IN     UINTN                              DataSize,
 | 
						|
  IN     UINT32                             Attributes OPTIONAL
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Finds variable in storage blocks of volatile and non-volatile storage areas.
 | 
						|
 | 
						|
  This code finds variable in storage blocks of volatile and non-volatile storage areas.
 | 
						|
  If VariableName is an empty string, then we just return the first
 | 
						|
  qualified variable without comparing VariableName and VendorGuid.
 | 
						|
 | 
						|
  @param[in]  VariableName          Name of the variable to be found.
 | 
						|
  @param[in]  VendorGuid            Variable vendor GUID to be found.
 | 
						|
  @param[out] Data                  Pointer to data address.
 | 
						|
  @param[out] DataSize              Pointer to data size.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER     If VariableName is not an empty string,
 | 
						|
                                    while VendorGuid is NULL.
 | 
						|
  @retval EFI_SUCCESS               Variable successfully found.
 | 
						|
  @retval EFI_NOT_FOUND             Variable not found
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
AuthServiceInternalFindVariable (
 | 
						|
  IN  CHAR16        *VariableName,
 | 
						|
  IN  EFI_GUID      *VendorGuid,
 | 
						|
  OUT VOID          **Data,
 | 
						|
  OUT UINTN         *DataSize
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Update the variable region with Variable information.
 | 
						|
 | 
						|
  @param[in] VariableName           Name of variable.
 | 
						|
  @param[in] VendorGuid             Guid of variable.
 | 
						|
  @param[in] Data                   Data pointer.
 | 
						|
  @param[in] DataSize               Size of Data.
 | 
						|
  @param[in] Attributes             Attribute value 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.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
AuthServiceInternalUpdateVariable (
 | 
						|
  IN CHAR16         *VariableName,
 | 
						|
  IN EFI_GUID       *VendorGuid,
 | 
						|
  IN VOID           *Data,
 | 
						|
  IN UINTN          DataSize,
 | 
						|
  IN UINT32         Attributes
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Update the variable region with Variable information.
 | 
						|
 | 
						|
  @param[in] VariableName           Name of variable.
 | 
						|
  @param[in] VendorGuid             Guid of variable.
 | 
						|
  @param[in] Data                   Data pointer.
 | 
						|
  @param[in] DataSize               Size of Data.
 | 
						|
  @param[in] Attributes             Attribute value of the variable.
 | 
						|
  @param[in] KeyIndex               Index of associated public key.
 | 
						|
  @param[in] MonotonicCount         Value of associated monotonic count.
 | 
						|
 | 
						|
  @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.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
AuthServiceInternalUpdateVariableWithMonotonicCount (
 | 
						|
  IN CHAR16         *VariableName,
 | 
						|
  IN EFI_GUID       *VendorGuid,
 | 
						|
  IN VOID           *Data,
 | 
						|
  IN UINTN          DataSize,
 | 
						|
  IN UINT32         Attributes,
 | 
						|
  IN UINT32         KeyIndex,
 | 
						|
  IN UINT64         MonotonicCount
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Update the variable region with Variable information.
 | 
						|
 | 
						|
  @param[in] VariableName           Name of variable.
 | 
						|
  @param[in] VendorGuid             Guid of variable.
 | 
						|
  @param[in] Data                   Data pointer.
 | 
						|
  @param[in] DataSize               Size of Data.
 | 
						|
  @param[in] Attributes             Attribute value of the variable.
 | 
						|
  @param[in] TimeStamp              Value of associated TimeStamp.
 | 
						|
 | 
						|
  @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.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
AuthServiceInternalUpdateVariableWithTimeStamp (
 | 
						|
  IN CHAR16         *VariableName,
 | 
						|
  IN EFI_GUID       *VendorGuid,
 | 
						|
  IN VOID           *Data,
 | 
						|
  IN UINTN          DataSize,
 | 
						|
  IN UINT32         Attributes,
 | 
						|
  IN EFI_TIME       *TimeStamp
 | 
						|
  );
 | 
						|
 | 
						|
#endif
 |