Home | History | Annotate | Download | only in DxeSecurityManagementLib
      1 /** @file
      2   Provides generic security measurement functions for DXE module.
      3 
      4 Copyright (c) 2009 - 2015, 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 <Protocol/LoadFile.h>
     17 #include <Library/DebugLib.h>
     18 #include <Library/DxeServicesLib.h>
     19 #include <Library/MemoryAllocationLib.h>
     20 #include <Library/SecurityManagementLib.h>
     21 #include <Library/DevicePathLib.h>
     22 #include <Library/UefiBootServicesTableLib.h>
     23 
     24 #define SECURITY_HANDLER_TABLE_SIZE   0x10
     25 
     26 //
     27 // Secruity Operation on Image and none Image.
     28 //
     29 #define EFI_AUTH_IMAGE_OPERATION_MASK       (EFI_AUTH_OPERATION_VERIFY_IMAGE \
     30                                               | EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD \
     31                                               | EFI_AUTH_OPERATION_MEASURE_IMAGE)
     32 #define EFI_AUTH_NONE_IMAGE_OPERATION_MASK  (EFI_AUTH_OPERATION_CONNECT_POLICY \
     33                                               | EFI_AUTH_OPERATION_AUTHENTICATION_STATE)
     34 
     35 typedef struct {
     36   UINT32  SecurityOperation;
     37   SECURITY_FILE_AUTHENTICATION_STATE_HANDLER  SecurityHandler;
     38 } SECURITY_INFO;
     39 
     40 typedef struct {
     41   UINT32  Security2Operation;
     42   SECURITY2_FILE_AUTHENTICATION_HANDLER  Security2Handler;
     43 } SECURITY2_INFO;
     44 
     45 UINT32  mCurrentAuthOperation       = 0;
     46 UINT32  mNumberOfSecurityHandler    = 0;
     47 UINT32  mMaxNumberOfSecurityHandler = 0;
     48 SECURITY_INFO  *mSecurityTable      = NULL;
     49 
     50 UINT32  mCurrentAuthOperation2       = 0;
     51 UINT32  mNumberOfSecurity2Handler    = 0;
     52 UINT32  mMaxNumberOfSecurity2Handler = 0;
     53 SECURITY2_INFO *mSecurity2Table      = NULL;
     54 
     55 /**
     56   Reallocates more global memory to store the registered Handler list.
     57 
     58   @retval  RETURN_SUCCESS            Reallocate memory successfully.
     59   @retval  RETURN_OUT_OF_RESOURCES   No enough memory to allocated.
     60 **/
     61 RETURN_STATUS
     62 EFIAPI
     63 ReallocateSecurityHandlerTable (
     64   )
     65 {
     66   //
     67   // Reallocate memory for security info structure.
     68   //
     69   mSecurityTable = ReallocatePool (
     70                      mMaxNumberOfSecurityHandler * sizeof (SECURITY_INFO),
     71                      (mMaxNumberOfSecurityHandler + SECURITY_HANDLER_TABLE_SIZE) * sizeof (SECURITY_INFO),
     72                      mSecurityTable
     73                      );
     74 
     75   //
     76   // No enough resource is allocated.
     77   //
     78   if (mSecurityTable == NULL) {
     79     return RETURN_OUT_OF_RESOURCES;
     80   }
     81 
     82   //
     83   // Increase max handler number
     84   //
     85   mMaxNumberOfSecurityHandler = mMaxNumberOfSecurityHandler + SECURITY_HANDLER_TABLE_SIZE;
     86   return RETURN_SUCCESS;
     87 }
     88 
     89 /**
     90  Check whether an operation is valid according to the requirement of current operation,
     91  which must make sure that the measure image operation is the last one.
     92 
     93  @param CurrentAuthOperation  Current operation.
     94  @param CheckAuthOperation    Operation to be checked.
     95 
     96  @retval  TRUE   Operation is valid for current operation.
     97  @retval  FALSE  Operation is invalid for current operation.
     98 **/
     99 BOOLEAN
    100 CheckAuthenticationOperation (
    101   IN  UINT32    CurrentAuthOperation,
    102   IN  UINT32    CheckAuthOperation
    103   )
    104 {
    105   //
    106   // Make sure new auth operation can be recognized.
    107   //
    108   ASSERT ((CheckAuthOperation & ~(EFI_AUTH_IMAGE_OPERATION_MASK | EFI_AUTH_OPERATION_AUTHENTICATION_STATE | EFI_AUTH_OPERATION_IMAGE_REQUIRED)) == 0);
    109 
    110   //
    111   // When current operation includes measure image operation,
    112   // only another measure image operation or none operation will be allowed.
    113   //
    114   if ((CurrentAuthOperation & EFI_AUTH_OPERATION_MEASURE_IMAGE) == EFI_AUTH_OPERATION_MEASURE_IMAGE) {
    115     if (((CheckAuthOperation & EFI_AUTH_OPERATION_MEASURE_IMAGE) == EFI_AUTH_OPERATION_MEASURE_IMAGE) ||
    116         ((CheckAuthOperation & EFI_AUTH_IMAGE_OPERATION_MASK) == EFI_AUTH_OPERATION_NONE)) {
    117       return TRUE;
    118     } else {
    119       return FALSE;
    120     }
    121   }
    122 
    123   //
    124   // When current operation doesn't include measure image operation,
    125   // any new operation will be allowed.
    126   //
    127   return TRUE;
    128 }
    129 
    130 /**
    131   Register security measurement handler with its operation type. The different
    132   handler with the same operation can all be registered.
    133 
    134   If SecurityHandler is NULL, then ASSERT().
    135   If no enough resources available to register new handler, then ASSERT().
    136   If AuthenticationOperation is not recongnized, then ASSERT().
    137   If the previous register handler can't be executed before the later register handler, then ASSERT().
    138 
    139   @param[in]  SecurityHandler           Security measurement service handler to be registered.
    140   @param[in]  AuthenticationOperation   Operation type is specified for the registered handler.
    141 
    142   @retval EFI_SUCCESS              The handlers were registered successfully.
    143 **/
    144 EFI_STATUS
    145 EFIAPI
    146 RegisterSecurityHandler (
    147   IN  SECURITY_FILE_AUTHENTICATION_STATE_HANDLER  SecurityHandler,
    148   IN  UINT32                                      AuthenticationOperation
    149   )
    150 {
    151   EFI_STATUS  Status;
    152 
    153   ASSERT (SecurityHandler != NULL);
    154 
    155   //
    156   // Make sure AuthenticationOperation is valid in the register order.
    157   //
    158   ASSERT (CheckAuthenticationOperation (mCurrentAuthOperation, AuthenticationOperation));
    159   mCurrentAuthOperation = mCurrentAuthOperation | AuthenticationOperation;
    160 
    161   //
    162   // Check whether the handler lists is enough to store new handler.
    163   //
    164   if (mNumberOfSecurityHandler == mMaxNumberOfSecurityHandler) {
    165     //
    166     // Allocate more resources for new handler.
    167     //
    168     Status = ReallocateSecurityHandlerTable();
    169     ASSERT_EFI_ERROR (Status);
    170   }
    171 
    172   //
    173   // Register new handler into the handler list.
    174   //
    175   mSecurityTable[mNumberOfSecurityHandler].SecurityOperation = AuthenticationOperation;
    176   mSecurityTable[mNumberOfSecurityHandler].SecurityHandler   = SecurityHandler;
    177   mNumberOfSecurityHandler ++;
    178 
    179   return EFI_SUCCESS;
    180 }
    181 
    182 /**
    183   Execute registered handlers until one returns an error and that error is returned.
    184   If none of the handlers return an error, then EFI_SUCCESS is returned.
    185 
    186   Before exectue handler, get the image buffer by file device path if a handler
    187   requires the image file. And return the image buffer to each handler when exectue handler.
    188 
    189   The handlers are executed in same order to their registered order.
    190 
    191   @param[in]  AuthenticationStatus
    192                            This is the authentication type returned from the Section
    193                            Extraction protocol. See the Section Extraction Protocol
    194                            Specification for details on this type.
    195   @param[in]  FilePath     This is a pointer to the device path of the file that is
    196                            being dispatched. This will optionally be used for logging.
    197 
    198   @retval EFI_SUCCESS            The file specified by File did authenticate when more
    199                                  than one security handler services were registered,
    200                                  or the file did not authenticate when no security
    201                                  handler service was registered. And the platform policy
    202                                  dictates that the DXE Core may use File.
    203   @retval EFI_INVALID_PARAMETER  File is NULL.
    204   @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
    205                                  the platform policy dictates that File should be placed
    206                                  in the untrusted state. A file may be promoted from
    207                                  the untrusted to the trusted state at a future time
    208                                  with a call to the Trust() DXE Service.
    209   @retval EFI_ACCESS_DENIED      The file specified by File did not authenticate, and
    210                                  the platform policy dictates that File should not be
    211                                  used for any purpose.
    212 **/
    213 EFI_STATUS
    214 EFIAPI
    215 ExecuteSecurityHandlers (
    216   IN  UINT32                            AuthenticationStatus,
    217   IN  CONST EFI_DEVICE_PATH_PROTOCOL    *FilePath
    218   )
    219 {
    220   UINT32        Index;
    221   EFI_STATUS    Status;
    222   UINT32        HandlerAuthenticationStatus;
    223   VOID          *FileBuffer;
    224   UINTN         FileSize;
    225   EFI_HANDLE    Handle;
    226   EFI_DEVICE_PATH_PROTOCOL        *Node;
    227   EFI_DEVICE_PATH_PROTOCOL        *FilePathToVerfiy;
    228 
    229   if (FilePath == NULL) {
    230     return EFI_INVALID_PARAMETER;
    231   }
    232 
    233   //
    234   // Directly return successfully when no handler is registered.
    235   //
    236   if (mNumberOfSecurityHandler == 0) {
    237     return EFI_SUCCESS;
    238   }
    239 
    240   Status                      = EFI_SUCCESS;
    241   FileBuffer                  = NULL;
    242   FileSize                    = 0;
    243   HandlerAuthenticationStatus = AuthenticationStatus;
    244   FilePathToVerfiy            = (EFI_DEVICE_PATH_PROTOCOL *) FilePath;
    245   //
    246   // Run security handler in same order to their registered list
    247   //
    248   for (Index = 0; Index < mNumberOfSecurityHandler; Index ++) {
    249     if ((mSecurityTable[Index].SecurityOperation & EFI_AUTH_OPERATION_IMAGE_REQUIRED) == EFI_AUTH_OPERATION_IMAGE_REQUIRED) {
    250       //
    251       // Try get file buffer when the handler requires image buffer.
    252       //
    253       if (FileBuffer == NULL) {
    254         Node   = FilePathToVerfiy;
    255         Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);
    256         //
    257         // Try to get image by FALSE boot policy for the exact boot file path.
    258         //
    259         FileBuffer = GetFileBufferByFilePath (FALSE, FilePath, &FileSize, &AuthenticationStatus);
    260         if (FileBuffer == NULL) {
    261           //
    262           // Try to get image by TRUE boot policy for the inexact boot file path.
    263           //
    264           FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, &FileSize, &AuthenticationStatus);
    265         }
    266         if ((FileBuffer != NULL) && (!EFI_ERROR (Status))) {
    267           //
    268           // LoadFile () may cause the device path of the Handle be updated.
    269           //
    270           FilePathToVerfiy = AppendDevicePath (DevicePathFromHandle (Handle), Node);
    271         }
    272       }
    273     }
    274     Status = mSecurityTable[Index].SecurityHandler (
    275                HandlerAuthenticationStatus,
    276                FilePathToVerfiy,
    277                FileBuffer,
    278                FileSize
    279                );
    280     if (EFI_ERROR (Status)) {
    281       break;
    282     }
    283   }
    284 
    285   if (FileBuffer != NULL) {
    286     FreePool (FileBuffer);
    287   }
    288   if (FilePathToVerfiy != FilePath) {
    289     FreePool (FilePathToVerfiy);
    290   }
    291 
    292   return Status;
    293 }
    294 
    295 /**
    296   Reallocates more global memory to store the registered Securit2Handler list.
    297 
    298   @retval  RETURN_SUCCESS            Reallocate memory successfully.
    299   @retval  RETURN_OUT_OF_RESOURCES   No enough memory to allocated.
    300 **/
    301 RETURN_STATUS
    302 EFIAPI
    303 ReallocateSecurity2HandlerTable (
    304   )
    305 {
    306   //
    307   // Reallocate memory for security info structure.
    308   //
    309   mSecurity2Table = ReallocatePool (
    310                      mMaxNumberOfSecurity2Handler * sizeof (SECURITY2_INFO),
    311                      (mMaxNumberOfSecurity2Handler + SECURITY_HANDLER_TABLE_SIZE) * sizeof (SECURITY2_INFO),
    312                      mSecurity2Table
    313                      );
    314 
    315   //
    316   // No enough resource is allocated.
    317   //
    318   if (mSecurity2Table == NULL) {
    319     return RETURN_OUT_OF_RESOURCES;
    320   }
    321 
    322   //
    323   // Increase max handler number
    324   //
    325   mMaxNumberOfSecurity2Handler = mMaxNumberOfSecurity2Handler + SECURITY_HANDLER_TABLE_SIZE;
    326   return RETURN_SUCCESS;
    327 }
    328 
    329 /**
    330   Check whether an operation is valid according to the requirement of current operation,
    331   which must make sure that the measure image operation is the last one.
    332 
    333   If AuthenticationOperation is not recongnized, return FALSE.
    334   If AuthenticationOperation is EFI_AUTH_OPERATION_NONE, return FALSE.
    335   If AuthenticationOperation includes security operation and authentication operation, return FALSE.
    336   If the previous register handler can't be executed before the later register handler, return FALSE.
    337 
    338   @param CurrentAuthOperation  Current operation.
    339   @param CheckAuthOperation    Operation to be checked.
    340 
    341   @retval  TRUE   Operation is valid for current operation.
    342   @retval  FALSE  Operation is invalid for current operation.
    343 **/
    344 BOOLEAN
    345 CheckAuthentication2Operation (
    346   IN  UINT32    CurrentAuthOperation,
    347   IN  UINT32    CheckAuthOperation
    348   )
    349 {
    350   //
    351   // Make sure new auth operation can be recognized.
    352   //
    353   if (CheckAuthOperation == EFI_AUTH_OPERATION_NONE) {
    354     return FALSE;
    355   }
    356   if ((CheckAuthOperation & ~(EFI_AUTH_IMAGE_OPERATION_MASK |
    357                               EFI_AUTH_NONE_IMAGE_OPERATION_MASK |
    358                               EFI_AUTH_OPERATION_IMAGE_REQUIRED)) != 0) {
    359     return FALSE;
    360   }
    361 
    362   //
    363   // When current operation includes measure image operation,
    364   // only another measure image or none image operation will be allowed.
    365   //
    366   if ((CurrentAuthOperation & EFI_AUTH_OPERATION_MEASURE_IMAGE) == EFI_AUTH_OPERATION_MEASURE_IMAGE) {
    367     if (((CheckAuthOperation & EFI_AUTH_OPERATION_MEASURE_IMAGE) == EFI_AUTH_OPERATION_MEASURE_IMAGE) ||
    368         ((CheckAuthOperation & EFI_AUTH_IMAGE_OPERATION_MASK) == 0)) {
    369       return TRUE;
    370     } else {
    371       return FALSE;
    372     }
    373   }
    374 
    375   //
    376   // Any other operation will be allowed.
    377   //
    378   return TRUE;
    379 }
    380 
    381 /**
    382   Register security measurement handler with its operation type. Different
    383   handlers with the same operation can all be registered.
    384 
    385   If Security2Handler is NULL, then ASSERT().
    386   If no enough resources available to register new handler, then ASSERT().
    387   If AuthenticationOperation is not recongnized, then ASSERT().
    388   If AuthenticationOperation is EFI_AUTH_OPERATION_NONE, then ASSERT().
    389   If the previous register handler can't be executed before the later register handler, then ASSERT().
    390 
    391   @param[in]  Security2Handler          The security measurement service handler to be registered.
    392   @param[in]  AuthenticationOperation   The operation type is specified for the registered handler.
    393 
    394   @retval EFI_SUCCESS              The handlers were registered successfully.
    395 **/
    396 EFI_STATUS
    397 EFIAPI
    398 RegisterSecurity2Handler (
    399   IN  SECURITY2_FILE_AUTHENTICATION_HANDLER       Security2Handler,
    400   IN  UINT32                                      AuthenticationOperation
    401   )
    402 {
    403   EFI_STATUS  Status;
    404 
    405   ASSERT (Security2Handler != NULL);
    406 
    407   //
    408   // Make sure AuthenticationOperation is valid in the register order.
    409   //
    410   ASSERT (CheckAuthentication2Operation (mCurrentAuthOperation2, AuthenticationOperation));
    411   mCurrentAuthOperation2 = mCurrentAuthOperation2 | AuthenticationOperation;
    412 
    413   //
    414   // Check whether the handler lists is enough to store new handler.
    415   //
    416   if (mNumberOfSecurity2Handler == mMaxNumberOfSecurity2Handler) {
    417     //
    418     // Allocate more resources for new handler.
    419     //
    420     Status = ReallocateSecurity2HandlerTable();
    421     ASSERT_EFI_ERROR (Status);
    422   }
    423 
    424   //
    425   // Register new handler into the handler list.
    426   //
    427   mSecurity2Table[mNumberOfSecurity2Handler].Security2Operation = AuthenticationOperation;
    428   mSecurity2Table[mNumberOfSecurity2Handler].Security2Handler   = Security2Handler;
    429   mNumberOfSecurity2Handler ++;
    430 
    431   return EFI_SUCCESS;
    432 }
    433 
    434 /**
    435   Execute registered handlers based on input AuthenticationOperation until
    436   one returns an error and that error is returned.
    437 
    438   If none of the handlers return an error, then EFI_SUCCESS is returned.
    439   The handlers those satisfy AuthenticationOperation will only be executed.
    440   The handlers are executed in same order to their registered order.
    441 
    442   @param[in]  AuthenticationOperation
    443                            The operation type specifies which handlers will be executed.
    444   @param[in]  AuthenticationStatus
    445                            The authentication status for the input file.
    446   @param[in]  File         This is a pointer to the device path of the file that is
    447                            being dispatched. This will optionally be used for logging.
    448   @param[in]  FileBuffer   A pointer to the buffer with the UEFI file image
    449   @param[in]  FileSize     The size of File buffer.
    450   @param[in]  BootPolicy   A boot policy that was used to call LoadImage() UEFI service.
    451 
    452   @retval EFI_SUCCESS             The file specified by DevicePath and non-NULL
    453                                   FileBuffer did authenticate, and the platform policy dictates
    454                                   that the DXE Foundation may use the file.
    455   @retval EFI_SUCCESS             The device path specified by NULL device path DevicePath
    456                                   and non-NULL FileBuffer did authenticate, and the platform
    457                                   policy dictates that the DXE Foundation may execute the image in
    458                                   FileBuffer.
    459   @retval EFI_SUCCESS             FileBuffer is NULL and current user has permission to start
    460                                   UEFI device drivers on the device path specified by DevicePath.
    461   @retval EFI_SECURITY_VIOLATION  The file specified by File or FileBuffer did not
    462                                   authenticate, and the platform policy dictates that
    463                                   the file should be placed in the untrusted state.
    464   @retval EFI_SECURITY_VIOLATION  FileBuffer FileBuffer is NULL and the user has no
    465                                   permission to start UEFI device drivers on the device path specified
    466                                   by DevicePath.
    467   @retval EFI_SECURITY_VIOLATION  FileBuffer is not NULL and the user has no permission to load
    468                                   drivers from the device path specified by DevicePath. The
    469                                   image has been added into the list of the deferred images.
    470   @retval EFI_ACCESS_DENIED       The file specified by File did not authenticate, and
    471                                   the platform policy dictates that the DXE
    472                                   Foundation may not use File.
    473   @retval EFI_INVALID_PARAMETER   File and FileBuffer are both NULL.
    474 **/
    475 EFI_STATUS
    476 EFIAPI
    477 ExecuteSecurity2Handlers (
    478   IN  UINT32                           AuthenticationOperation,
    479   IN  UINT32                           AuthenticationStatus,
    480   IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,
    481   IN  VOID                             *FileBuffer,
    482   IN  UINTN                            FileSize,
    483   IN  BOOLEAN                          BootPolicy
    484   )
    485 {
    486   UINT32        Index;
    487   EFI_STATUS    Status;
    488 
    489   //
    490   // Invalid case if File and FileBuffer are both NULL.
    491   //
    492   if (File == NULL && FileBuffer == NULL) {
    493     return EFI_INVALID_PARAMETER;
    494   }
    495 
    496   //
    497   // Directly return successfully when no handler is registered.
    498   //
    499   if (mNumberOfSecurity2Handler == 0) {
    500     return EFI_SUCCESS;
    501   }
    502 
    503   //
    504   // Run security handler in same order to their registered list
    505   //
    506   for (Index = 0; Index < mNumberOfSecurity2Handler; Index ++) {
    507     //
    508     // If FileBuffer is not NULL, the input is Image, which will be handled by EFI_AUTH_IMAGE_OPERATION_MASK operation.
    509     // If FileBuffer is NULL, the input is not Image, which will be handled by EFI_AUTH_NONE_IMAGE_OPERATION_MASK operation.
    510     // Other cases are ignored.
    511     //
    512     if ((FileBuffer != NULL && (mSecurity2Table[Index].Security2Operation & EFI_AUTH_IMAGE_OPERATION_MASK) != 0) ||
    513         (FileBuffer == NULL && (mSecurity2Table[Index].Security2Operation & EFI_AUTH_NONE_IMAGE_OPERATION_MASK) != 0)) {
    514       //
    515       // Execute registered handlers based on input AuthenticationOperation
    516       //
    517       if ((mSecurity2Table[Index].Security2Operation & AuthenticationOperation) != 0) {
    518         Status = mSecurity2Table[Index].Security2Handler (
    519                    AuthenticationStatus,
    520                    File,
    521                    FileBuffer,
    522                    FileSize,
    523                    BootPolicy
    524                    );
    525         if (EFI_ERROR (Status)) {
    526           return Status;
    527         }
    528       }
    529     }
    530   }
    531 
    532   return EFI_SUCCESS;
    533 }
    534