Home | History | Annotate | Download | only in SmmTcg2PhysicalPresenceLib
      1 /** @file
      2   Handle TPM 2.0 physical presence requests from OS.
      3 
      4   This library will handle TPM 2.0 physical presence request from OS.
      5 
      6   Caution: This module requires additional review when modified.
      7   This driver will have external input - variable.
      8   This external input must be validated carefully to avoid security issue.
      9 
     10   Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction() and Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction()
     11   will receive untrusted input and do validation.
     12 
     13 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
     14 This program and the accompanying materials
     15 are licensed and made available under the terms and conditions of the BSD License
     16 which accompanies this distribution.  The full text of the license may be found at
     17 http://opensource.org/licenses/bsd-license.php
     18 
     19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     21 
     22 **/
     23 
     24 #include <PiSmm.h>
     25 
     26 #include <Guid/Tcg2PhysicalPresenceData.h>
     27 
     28 #include <Protocol/SmmVariable.h>
     29 
     30 #include <Library/DebugLib.h>
     31 #include <Library/BaseMemoryLib.h>
     32 #include <Library/Tcg2PpVendorLib.h>
     33 #include <Library/SmmServicesTableLib.h>
     34 
     35 EFI_SMM_VARIABLE_PROTOCOL  *mTcg2PpSmmVariable;
     36 
     37 /**
     38   The handler for TPM physical presence function:
     39   Return TPM Operation Response to OS Environment.
     40 
     41   This API should be invoked in OS runtime phase to interface with ACPI method.
     42 
     43   @param[out]     MostRecentRequest Most recent operation request.
     44   @param[out]     Response          Response to the most recent operation request.
     45 
     46   @return Return Code for Return TPM Operation Response to OS Environment.
     47 **/
     48 UINT32
     49 EFIAPI
     50 Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
     51   OUT UINT32                *MostRecentRequest,
     52   OUT UINT32                *Response
     53   )
     54 {
     55   EFI_STATUS                        Status;
     56   UINTN                             DataSize;
     57   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
     58 
     59   DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
     60 
     61   //
     62   // Get the Physical Presence variable
     63   //
     64   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
     65   Status = mTcg2PpSmmVariable->SmmGetVariable (
     66                                  TCG2_PHYSICAL_PRESENCE_VARIABLE,
     67                                  &gEfiTcg2PhysicalPresenceGuid,
     68                                  NULL,
     69                                  &DataSize,
     70                                  &PpData
     71                                  );
     72   if (EFI_ERROR (Status)) {
     73     *MostRecentRequest = 0;
     74     *Response          = 0;
     75     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
     76     return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
     77   }
     78 
     79   *MostRecentRequest = PpData.LastPPRequest;
     80   *Response          = PpData.PPResponse;
     81 
     82   return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
     83 }
     84 
     85 /**
     86   The handler for TPM physical presence function:
     87   Submit TPM Operation Request to Pre-OS Environment and
     88   Submit TPM Operation Request to Pre-OS Environment 2.
     89 
     90   This API should be invoked in OS runtime phase to interface with ACPI method.
     91 
     92   Caution: This function may receive untrusted input.
     93 
     94   @param[in, out]  Pointer to OperationRequest TPM physical presence operation request.
     95   @param[in, out]  Pointer to RequestParameter TPM physical presence operation request parameter.
     96 
     97   @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
     98         Submit TPM Operation Request to Pre-OS Environment 2.
     99   **/
    100 UINT32
    101 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
    102   IN OUT UINT32               *OperationRequest,
    103   IN OUT UINT32               *RequestParameter
    104   )
    105 {
    106   EFI_STATUS                        Status;
    107   UINT32                            ReturnCode;
    108   UINTN                             DataSize;
    109   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
    110   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags;
    111 
    112   DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", *OperationRequest, *RequestParameter));
    113   ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
    114 
    115   //
    116   // Get the Physical Presence variable
    117   //
    118   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
    119   Status = mTcg2PpSmmVariable->SmmGetVariable (
    120                                  TCG2_PHYSICAL_PRESENCE_VARIABLE,
    121                                  &gEfiTcg2PhysicalPresenceGuid,
    122                                  NULL,
    123                                  &DataSize,
    124                                  &PpData
    125                                  );
    126   if (EFI_ERROR (Status)) {
    127     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
    128     ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
    129     goto EXIT;
    130   }
    131 
    132   if ((*OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
    133       (*OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
    134     ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
    135     goto EXIT;
    136   }
    137 
    138   if ((PpData.PPRequest != *OperationRequest) ||
    139       (PpData.PPRequestParameter != *RequestParameter)) {
    140     PpData.PPRequest = (UINT8)*OperationRequest;
    141     PpData.PPRequestParameter = *RequestParameter;
    142     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
    143     Status = mTcg2PpSmmVariable->SmmSetVariable (
    144                                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
    145                                    &gEfiTcg2PhysicalPresenceGuid,
    146                                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    147                                    DataSize,
    148                                    &PpData
    149                                    );
    150     if (EFI_ERROR (Status)) {
    151       DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
    152       ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
    153       goto EXIT;
    154     }
    155   }
    156 
    157   if (*OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
    158     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
    159     Status = mTcg2PpSmmVariable->SmmGetVariable (
    160                                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
    161                                    &gEfiTcg2PhysicalPresenceGuid,
    162                                    NULL,
    163                                    &DataSize,
    164                                    &Flags
    165                                    );
    166     if (EFI_ERROR (Status)) {
    167       Flags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT | TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_DEFAULT;
    168     }
    169     ReturnCode = Tcg2PpVendorLibSubmitRequestToPreOSFunction (*OperationRequest, Flags.PPFlags, *RequestParameter);
    170   }
    171 
    172 EXIT:
    173   //
    174   // Sync PPRQ/PPRM from PP Variable if PP submission fails
    175   //
    176   if (ReturnCode != TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
    177     DEBUG ((EFI_D_ERROR, "[TPM2] Submit PP Request failure! Sync PPRQ/PPRM with PP variable.\n", Status));
    178     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
    179     ZeroMem(&PpData, DataSize);
    180     Status = mTcg2PpSmmVariable->SmmGetVariable (
    181                                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
    182                                    &gEfiTcg2PhysicalPresenceGuid,
    183                                    NULL,
    184                                    &DataSize,
    185                                    &PpData
    186                                    );
    187     *OperationRequest = (UINT32)PpData.PPRequest;
    188     *RequestParameter = PpData.PPRequestParameter;
    189   }
    190 
    191   return ReturnCode;
    192 }
    193 
    194 /**
    195   The handler for TPM physical presence function:
    196   Submit TPM Operation Request to Pre-OS Environment and
    197   Submit TPM Operation Request to Pre-OS Environment 2.
    198 
    199   This API should be invoked in OS runtime phase to interface with ACPI method.
    200 
    201   Caution: This function may receive untrusted input.
    202 
    203   @param[in]      OperationRequest TPM physical presence operation request.
    204   @param[in]      RequestParameter TPM physical presence operation request parameter.
    205 
    206   @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
    207           Submit TPM Operation Request to Pre-OS Environment 2.
    208 **/
    209 UINT32
    210 EFIAPI
    211 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
    212   IN UINT32                 OperationRequest,
    213   IN UINT32                 RequestParameter
    214   )
    215 {
    216   UINT32                 TempOperationRequest;
    217   UINT32                 TempRequestParameter;
    218 
    219   TempOperationRequest = OperationRequest;
    220   TempRequestParameter = RequestParameter;
    221 
    222   return Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx(&TempOperationRequest, &TempRequestParameter);
    223 }
    224 
    225 /**
    226   The handler for TPM physical presence function:
    227   Get User Confirmation Status for Operation.
    228 
    229   This API should be invoked in OS runtime phase to interface with ACPI method.
    230 
    231   Caution: This function may receive untrusted input.
    232 
    233   @param[in]      OperationRequest TPM physical presence operation request.
    234 
    235   @return Return Code for Get User Confirmation Status for Operation.
    236 **/
    237 UINT32
    238 EFIAPI
    239 Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (
    240   IN UINT32                 OperationRequest
    241   )
    242 {
    243   EFI_STATUS                        Status;
    244   UINTN                             DataSize;
    245   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
    246   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags;
    247   BOOLEAN                           RequestConfirmed;
    248 
    249   DEBUG ((EFI_D_INFO, "[TPM2] GetUserConfirmationStatusFunction, Request = %x\n", OperationRequest));
    250 
    251   //
    252   // Get the Physical Presence variable
    253   //
    254   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
    255   Status = mTcg2PpSmmVariable->SmmGetVariable (
    256                                  TCG2_PHYSICAL_PRESENCE_VARIABLE,
    257                                  &gEfiTcg2PhysicalPresenceGuid,
    258                                  NULL,
    259                                  &DataSize,
    260                                  &PpData
    261                                  );
    262   if (EFI_ERROR (Status)) {
    263     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
    264     return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
    265   }
    266   //
    267   // Get the Physical Presence flags
    268   //
    269   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
    270   Status = mTcg2PpSmmVariable->SmmGetVariable (
    271                                  TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
    272                                  &gEfiTcg2PhysicalPresenceGuid,
    273                                  NULL,
    274                                  &DataSize,
    275                                  &Flags
    276                                  );
    277   if (EFI_ERROR (Status)) {
    278     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP flags failure! Status = %r\n", Status));
    279     return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
    280   }
    281 
    282   RequestConfirmed = FALSE;
    283 
    284   switch (OperationRequest) {
    285     case TCG2_PHYSICAL_PRESENCE_CLEAR:
    286     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
    287     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
    288     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
    289       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
    290         RequestConfirmed = TRUE;
    291       }
    292       break;
    293 
    294     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
    295       RequestConfirmed = TRUE;
    296       break;
    297 
    298     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
    299       break;
    300 
    301     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
    302       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
    303         RequestConfirmed = TRUE;
    304       }
    305       break;
    306 
    307     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
    308       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
    309         RequestConfirmed = TRUE;
    310       }
    311       break;
    312 
    313     case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
    314       RequestConfirmed = TRUE;
    315       break;
    316 
    317     case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
    318       if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) {
    319         RequestConfirmed = TRUE;
    320       }
    321       break;
    322 
    323     case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
    324       if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) {
    325         RequestConfirmed = TRUE;
    326       }
    327       break;
    328 
    329     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
    330     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
    331       RequestConfirmed = TRUE;
    332       break;
    333 
    334     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
    335     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
    336       break;
    337 
    338     default:
    339       if (OperationRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
    340         RequestConfirmed = TRUE;
    341       } else {
    342         if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
    343           return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
    344         }
    345       }
    346       break;
    347   }
    348 
    349   if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
    350     return Tcg2PpVendorLibGetUserConfirmationStatusFunction (OperationRequest, Flags.PPFlags);
    351   }
    352 
    353   if (RequestConfirmed) {
    354     return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED;
    355   } else {
    356     return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED;
    357   }
    358 }
    359 
    360 /**
    361   The constructor function locates SmmVariable protocol.
    362 
    363   It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
    364 
    365   @param  ImageHandle   The firmware allocated handle for the EFI image.
    366   @param  SystemTable   A pointer to the EFI System Table.
    367 
    368   @retval EFI_SUCCESS   The constructor successfully added string package.
    369   @retval Other value   The constructor can't add string package.
    370 **/
    371 EFI_STATUS
    372 EFIAPI
    373 Tcg2PhysicalPresenceLibConstructor (
    374   IN EFI_HANDLE        ImageHandle,
    375   IN EFI_SYSTEM_TABLE  *SystemTable
    376   )
    377 {
    378   EFI_STATUS  Status;
    379 
    380   //
    381   // Locate SmmVariableProtocol.
    382   //
    383   Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mTcg2PpSmmVariable);
    384   ASSERT_EFI_ERROR (Status);
    385 
    386   return EFI_SUCCESS;
    387 }
    388