Home | History | Annotate | Download | only in DxeImageVerificationLib
      1 /** @file
      2   Measure TrEE required variable.
      3 
      4 Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include <PiDxe.h>
     16 #include <Guid/ImageAuthentication.h>
     17 #include <IndustryStandard/UefiTcgPlatform.h>
     18 #include <Protocol/TrEEProtocol.h>
     19 
     20 #include <Library/UefiBootServicesTableLib.h>
     21 #include <Library/UefiRuntimeServicesTableLib.h>
     22 #include <Library/MemoryAllocationLib.h>
     23 #include <Library/BaseMemoryLib.h>
     24 #include <Library/DebugLib.h>
     25 #include <Library/BaseLib.h>
     26 #include <Library/TpmMeasurementLib.h>
     27 
     28 typedef struct {
     29   CHAR16                                 *VariableName;
     30   EFI_GUID                               *VendorGuid;
     31 } VARIABLE_TYPE;
     32 
     33 typedef struct {
     34   CHAR16                                 *VariableName;
     35   EFI_GUID                               *VendorGuid;
     36   VOID                                   *Data;
     37   UINTN                                  Size;
     38 } VARIABLE_RECORD;
     39 
     40 #define  MEASURED_AUTHORITY_COUNT_MAX  0x100
     41 
     42 UINTN            mMeasuredAuthorityCount    = 0;
     43 UINTN            mMeasuredAuthorityCountMax = 0;
     44 VARIABLE_RECORD  *mMeasuredAuthorityList    = NULL;
     45 
     46 VARIABLE_TYPE  mVariableType[] = {
     47   {EFI_IMAGE_SECURITY_DATABASE,  &gEfiImageSecurityDatabaseGuid},
     48 };
     49 
     50 /**
     51   This function will check if VarName should be recorded and return the address of VarName if it is needed.
     52 
     53   @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.
     54 
     55   @return the address of VarName.
     56 **/
     57 CHAR16 *
     58 AssignVarName (
     59   IN      CHAR16                    *VarName
     60   )
     61 {
     62   UINTN  Index;
     63 
     64   for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
     65     if (StrCmp (VarName, mVariableType[Index].VariableName) == 0) {
     66       return mVariableType[Index].VariableName;
     67     }
     68   }
     69 
     70   return NULL;
     71 }
     72 
     73 /**
     74   This function will check if VendorGuid should be recorded and return the address of VendorGuid if it is needed.
     75 
     76   @param[in]  VendorGuid        A unique identifier for the vendor.
     77 
     78   @return the address of VendorGuid.
     79 **/
     80 EFI_GUID *
     81 AssignVendorGuid (
     82   IN      EFI_GUID                  *VendorGuid
     83   )
     84 {
     85   UINTN  Index;
     86 
     87   for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
     88     if (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid)) {
     89       return mVariableType[Index].VendorGuid;
     90     }
     91   }
     92 
     93   return NULL;
     94 }
     95 
     96 /**
     97   This function will add variable information to MeasuredAuthorityList.
     98 
     99   @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.
    100   @param[in]  VendorGuid        A unique identifier for the vendor.
    101   @param[in]  VarData           The content of the variable data.
    102   @param[in]  VarSize           The size of the variable data.
    103 
    104   @retval EFI_SUCCESS           Operation completed successfully.
    105   @retval EFI_OUT_OF_RESOURCES  Out of memory.
    106 **/
    107 EFI_STATUS
    108 AddDataMeasured (
    109   IN      CHAR16                    *VarName,
    110   IN      EFI_GUID                  *VendorGuid,
    111   IN      VOID                      *Data,
    112   IN      UINTN                     Size
    113   )
    114 {
    115   VARIABLE_RECORD  *NewMeasuredAuthorityList;
    116 
    117   ASSERT (mMeasuredAuthorityCount <= mMeasuredAuthorityCountMax);
    118   if (mMeasuredAuthorityCount == mMeasuredAuthorityCountMax) {
    119     //
    120     // Need enlarge
    121     //
    122     NewMeasuredAuthorityList = AllocateZeroPool (sizeof(VARIABLE_RECORD) * (mMeasuredAuthorityCountMax + MEASURED_AUTHORITY_COUNT_MAX));
    123     if (NewMeasuredAuthorityList == NULL) {
    124       return EFI_OUT_OF_RESOURCES;
    125     }
    126     if (mMeasuredAuthorityList != NULL) {
    127       CopyMem (NewMeasuredAuthorityList, mMeasuredAuthorityList, sizeof(VARIABLE_RECORD) * mMeasuredAuthorityCount);
    128       FreePool (mMeasuredAuthorityList);
    129     }
    130     mMeasuredAuthorityList     = NewMeasuredAuthorityList;
    131     mMeasuredAuthorityCountMax += MEASURED_AUTHORITY_COUNT_MAX;
    132   }
    133 
    134   //
    135   // Add new entry
    136   //
    137   mMeasuredAuthorityList[mMeasuredAuthorityCount].VariableName = AssignVarName (VarName);
    138   mMeasuredAuthorityList[mMeasuredAuthorityCount].VendorGuid   = AssignVendorGuid (VendorGuid);
    139   mMeasuredAuthorityList[mMeasuredAuthorityCount].Size         = Size;
    140   mMeasuredAuthorityList[mMeasuredAuthorityCount].Data         = AllocatePool (Size);
    141   if (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data == NULL) {
    142     return EFI_OUT_OF_RESOURCES;
    143   }
    144   CopyMem (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data, Data, Size);
    145   mMeasuredAuthorityCount++;
    146 
    147   return EFI_SUCCESS;
    148 }
    149 
    150 /**
    151   This function will return if this variable is already measured.
    152 
    153   @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.
    154   @param[in]  VendorGuid        A unique identifier for the vendor.
    155   @param[in]  VarData           The content of the variable data.
    156   @param[in]  VarSize           The size of the variable data.
    157 
    158   @retval TRUE  The data is already measured.
    159   @retval FALSE The data is not measured yet.
    160 **/
    161 BOOLEAN
    162 IsDataMeasured (
    163   IN      CHAR16                    *VarName,
    164   IN      EFI_GUID                  *VendorGuid,
    165   IN      VOID                      *Data,
    166   IN      UINTN                     Size
    167   )
    168 {
    169   UINTN  Index;
    170 
    171   for (Index = 0; Index < mMeasuredAuthorityCount; Index++) {
    172     if ((StrCmp (VarName, mMeasuredAuthorityList[Index].VariableName) == 0) &&
    173         (CompareGuid (VendorGuid, mMeasuredAuthorityList[Index].VendorGuid)) &&
    174         (CompareMem (Data, mMeasuredAuthorityList[Index].Data, Size) == 0) &&
    175         (Size == mMeasuredAuthorityList[Index].Size)) {
    176       return TRUE;
    177     }
    178   }
    179 
    180   return FALSE;
    181 }
    182 
    183 /**
    184   This function will return if this variable is SecureAuthority Variable.
    185 
    186   @param[in]  VariableName      A Null-terminated string that is the name of the vendor's variable.
    187   @param[in]  VendorGuid        A unique identifier for the vendor.
    188 
    189   @retval TRUE  This is SecureAuthority Variable
    190   @retval FALSE This is not SecureAuthority Variable
    191 **/
    192 BOOLEAN
    193 IsSecureAuthorityVariable (
    194   IN CHAR16                                 *VariableName,
    195   IN EFI_GUID                               *VendorGuid
    196   )
    197 {
    198   UINTN   Index;
    199 
    200   for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
    201     if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) &&
    202         (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) {
    203       return TRUE;
    204     }
    205   }
    206   return FALSE;
    207 }
    208 
    209 /**
    210   Measure and log an EFI variable, and extend the measurement result into a specific PCR.
    211 
    212   @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.
    213   @param[in]  VendorGuid        A unique identifier for the vendor.
    214   @param[in]  VarData           The content of the variable data.
    215   @param[in]  VarSize           The size of the variable data.
    216 
    217   @retval EFI_SUCCESS           Operation completed successfully.
    218   @retval EFI_OUT_OF_RESOURCES  Out of memory.
    219   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
    220 
    221 **/
    222 EFI_STATUS
    223 EFIAPI
    224 MeasureVariable (
    225   IN      CHAR16                    *VarName,
    226   IN      EFI_GUID                  *VendorGuid,
    227   IN      VOID                      *VarData,
    228   IN      UINTN                     VarSize
    229   )
    230 {
    231   EFI_STATUS                        Status;
    232   UINTN                             VarNameLength;
    233   EFI_VARIABLE_DATA_TREE            *VarLog;
    234   UINT32                            VarLogSize;
    235 
    236   //
    237   // The EFI_VARIABLE_DATA_TREE.VariableData value shall be the EFI_SIGNATURE_DATA value
    238   // from the EFI_SIGNATURE_LIST that contained the authority that was used to validate the image
    239   //
    240   VarNameLength      = StrLen (VarName);
    241   VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
    242                         - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
    243 
    244   VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize);
    245   if (VarLog == NULL) {
    246     return EFI_OUT_OF_RESOURCES;
    247   }
    248 
    249   CopyMem (&VarLog->VariableName, VendorGuid, sizeof(VarLog->VariableName));
    250   VarLog->UnicodeNameLength  = VarNameLength;
    251   VarLog->VariableDataLength = VarSize;
    252   CopyMem (
    253      VarLog->UnicodeName,
    254      VarName,
    255      VarNameLength * sizeof (*VarName)
    256      );
    257   CopyMem (
    258      (CHAR16 *)VarLog->UnicodeName + VarNameLength,
    259      VarData,
    260      VarSize
    261      );
    262 
    263   DEBUG ((EFI_D_INFO, "DxeImageVerification: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY));
    264   DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
    265 
    266   Status = TpmMeasureAndLogData (
    267              7,
    268              EV_EFI_VARIABLE_AUTHORITY,
    269              VarLog,
    270              VarLogSize,
    271              VarLog,
    272              VarLogSize
    273              );
    274   FreePool (VarLog);
    275 
    276   return Status;
    277 }
    278 
    279 /**
    280   SecureBoot Hook for processing image verification.
    281 
    282   @param[in] VariableName                 Name of Variable to be found.
    283   @param[in] VendorGuid                   Variable vendor GUID.
    284   @param[in] DataSize                     Size of Data found. If size is less than the
    285                                           data, this value contains the required size.
    286   @param[in] Data                         Data pointer.
    287 
    288 **/
    289 VOID
    290 EFIAPI
    291 SecureBootHook (
    292   IN CHAR16                                 *VariableName,
    293   IN EFI_GUID                               *VendorGuid,
    294   IN UINTN                                  DataSize,
    295   IN VOID                                   *Data
    296   )
    297 {
    298   EFI_STATUS                        Status;
    299 
    300   if (!IsSecureAuthorityVariable (VariableName, VendorGuid)) {
    301     return ;
    302   }
    303 
    304   if (IsDataMeasured (VariableName, VendorGuid, Data, DataSize)) {
    305     DEBUG ((EFI_D_ERROR, "MeasureSecureAuthorityVariable - IsDataMeasured\n"));
    306     return ;
    307   }
    308 
    309   Status = MeasureVariable (
    310              VariableName,
    311              VendorGuid,
    312              Data,
    313              DataSize
    314              );
    315   DEBUG ((EFI_D_INFO, "MeasureBootPolicyVariable - %r\n", Status));
    316 
    317   if (!EFI_ERROR (Status)) {
    318     AddDataMeasured (VariableName, VendorGuid, Data, DataSize);
    319   }
    320 
    321   return ;
    322 }
    323