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
ReallocateSecurityHandlerTable()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
CheckAuthenticationOperation(IN UINT32 CurrentAuthOperation,IN UINT32 CheckAuthOperation)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
RegisterSecurityHandler(IN SECURITY_FILE_AUTHENTICATION_STATE_HANDLER SecurityHandler,IN UINT32 AuthenticationOperation)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
ExecuteSecurityHandlers(IN UINT32 AuthenticationStatus,IN CONST EFI_DEVICE_PATH_PROTOCOL * FilePath)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
ReallocateSecurity2HandlerTable()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
CheckAuthentication2Operation(IN UINT32 CurrentAuthOperation,IN UINT32 CheckAuthOperation)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
RegisterSecurity2Handler(IN SECURITY2_FILE_AUTHENTICATION_HANDLER Security2Handler,IN UINT32 AuthenticationOperation)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
ExecuteSecurity2Handlers(IN UINT32 AuthenticationOperation,IN UINT32 AuthenticationStatus,IN CONST EFI_DEVICE_PATH_PROTOCOL * File,IN VOID * FileBuffer,IN UINTN FileSize,IN BOOLEAN BootPolicy)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