Home | History | Annotate | Download | only in RuntimeDxe
      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 VARIABLE_TYPE  mVariableType[] = {
     34   {EFI_SECURE_BOOT_MODE_NAME,    &gEfiGlobalVariableGuid},
     35   {EFI_PLATFORM_KEY_NAME,        &gEfiGlobalVariableGuid},
     36   {EFI_KEY_EXCHANGE_KEY_NAME,    &gEfiGlobalVariableGuid},
     37   {EFI_IMAGE_SECURITY_DATABASE,  &gEfiImageSecurityDatabaseGuid},
     38   {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},
     39 };
     40 
     41 /**
     42   This function will return if this variable is SecureBootPolicy Variable.
     43 
     44   @param[in]  VariableName      A Null-terminated string that is the name of the vendor's variable.
     45   @param[in]  VendorGuid        A unique identifier for the vendor.
     46 
     47   @retval TRUE  This is SecureBootPolicy Variable
     48   @retval FALSE This is not SecureBootPolicy Variable
     49 **/
     50 BOOLEAN
     51 IsSecureBootPolicyVariable (
     52   IN CHAR16                                 *VariableName,
     53   IN EFI_GUID                               *VendorGuid
     54   )
     55 {
     56   UINTN   Index;
     57 
     58   for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
     59     if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) &&
     60         (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) {
     61       return TRUE;
     62     }
     63   }
     64   return FALSE;
     65 }
     66 
     67 /**
     68   Measure and log an EFI variable, and extend the measurement result into a specific PCR.
     69 
     70   @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.
     71   @param[in]  VendorGuid        A unique identifier for the vendor.
     72   @param[in]  VarData           The content of the variable data.
     73   @param[in]  VarSize           The size of the variable data.
     74 
     75   @retval EFI_SUCCESS           Operation completed successfully.
     76   @retval EFI_OUT_OF_RESOURCES  Out of memory.
     77   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
     78 
     79 **/
     80 EFI_STATUS
     81 EFIAPI
     82 MeasureVariable (
     83   IN      CHAR16                    *VarName,
     84   IN      EFI_GUID                  *VendorGuid,
     85   IN      VOID                      *VarData,
     86   IN      UINTN                     VarSize
     87   )
     88 {
     89   EFI_STATUS                        Status;
     90   UINTN                             VarNameLength;
     91   EFI_VARIABLE_DATA_TREE            *VarLog;
     92   UINT32                            VarLogSize;
     93 
     94   ASSERT ((VarSize == 0 && VarData == NULL) || (VarSize != 0 && VarData != NULL));
     95 
     96   VarNameLength      = StrLen (VarName);
     97   VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
     98                         - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
     99 
    100   VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize);
    101   if (VarLog == NULL) {
    102     return EFI_OUT_OF_RESOURCES;
    103   }
    104 
    105   CopyMem (&VarLog->VariableName, VendorGuid, sizeof(VarLog->VariableName));
    106   VarLog->UnicodeNameLength  = VarNameLength;
    107   VarLog->VariableDataLength = VarSize;
    108   CopyMem (
    109      VarLog->UnicodeName,
    110      VarName,
    111      VarNameLength * sizeof (*VarName)
    112      );
    113   if (VarSize != 0) {
    114     CopyMem (
    115        (CHAR16 *)VarLog->UnicodeName + VarNameLength,
    116        VarData,
    117        VarSize
    118        );
    119   }
    120 
    121   DEBUG ((EFI_D_INFO, "AuthVariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY));
    122   DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
    123 
    124   Status = TpmMeasureAndLogData (
    125              7,
    126              EV_EFI_VARIABLE_DRIVER_CONFIG,
    127              VarLog,
    128              VarLogSize,
    129              VarLog,
    130              VarLogSize
    131              );
    132   FreePool (VarLog);
    133   return Status;
    134 }
    135 
    136 /**
    137   Returns the status whether get the variable success. The function retrieves
    138   variable  through the UEFI Runtime Service GetVariable().  The
    139   returned buffer is allocated using AllocatePool().  The caller is responsible
    140   for freeing this buffer with FreePool().
    141 
    142   This API is only invoked in boot time. It may NOT be invoked at runtime.
    143 
    144   @param[in]  Name  The pointer to a Null-terminated Unicode string.
    145   @param[in]  Guid  The pointer to an EFI_GUID structure
    146   @param[out] Value The buffer point saved the variable info.
    147   @param[out] Size  The buffer size of the variable.
    148 
    149   @return EFI_OUT_OF_RESOURCES      Allocate buffer failed.
    150   @return EFI_SUCCESS               Find the specified variable.
    151   @return Others Errors             Return errors from call to gRT->GetVariable.
    152 
    153 **/
    154 EFI_STATUS
    155 InternalGetVariable (
    156   IN CONST CHAR16    *Name,
    157   IN CONST EFI_GUID  *Guid,
    158   OUT VOID           **Value,
    159   OUT UINTN          *Size
    160   )
    161 {
    162   EFI_STATUS  Status;
    163   UINTN       BufferSize;
    164 
    165   //
    166   // Try to get the variable size.
    167   //
    168   BufferSize = 0;
    169   *Value     = NULL;
    170   if (Size != NULL) {
    171     *Size  = 0;
    172   }
    173 
    174   Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);
    175   if (Status != EFI_BUFFER_TOO_SMALL) {
    176     return Status;
    177   }
    178 
    179   //
    180   // Allocate buffer to get the variable.
    181   //
    182   *Value = AllocatePool (BufferSize);
    183   ASSERT (*Value != NULL);
    184   if (*Value == NULL) {
    185     return EFI_OUT_OF_RESOURCES;
    186   }
    187 
    188   //
    189   // Get the variable data.
    190   //
    191   Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);
    192   if (EFI_ERROR (Status)) {
    193     FreePool(*Value);
    194     *Value = NULL;
    195   }
    196 
    197   if (Size != NULL) {
    198     *Size = BufferSize;
    199   }
    200 
    201   return Status;
    202 }
    203 
    204 /**
    205   SecureBoot Hook for SetVariable.
    206 
    207   @param[in] VariableName                 Name of Variable to be found.
    208   @param[in] VendorGuid                   Variable vendor GUID.
    209 
    210 **/
    211 VOID
    212 EFIAPI
    213 SecureBootHook (
    214   IN CHAR16                                 *VariableName,
    215   IN EFI_GUID                               *VendorGuid
    216   )
    217 {
    218   EFI_STATUS                        Status;
    219   UINTN                             VariableDataSize;
    220   VOID                              *VariableData;
    221 
    222   if (!IsSecureBootPolicyVariable (VariableName, VendorGuid)) {
    223     return ;
    224   }
    225 
    226   //
    227   // We should NOT use Data and DataSize here,because it may include signature,
    228   // or is just partial with append attributes, or is deleted.
    229   // We should GetVariable again, to get full variable content.
    230   //
    231   Status = InternalGetVariable (
    232              VariableName,
    233              VendorGuid,
    234              &VariableData,
    235              &VariableDataSize
    236              );
    237   if (EFI_ERROR (Status)) {
    238     VariableData     = NULL;
    239     VariableDataSize = 0;
    240   }
    241 
    242   Status = MeasureVariable (
    243              VariableName,
    244              VendorGuid,
    245              VariableData,
    246              VariableDataSize
    247              );
    248   DEBUG ((EFI_D_INFO, "MeasureBootPolicyVariable - %r\n", Status));
    249 
    250   if (VariableData != NULL) {
    251     FreePool (VariableData);
    252   }
    253 
    254   return ;
    255 }
    256