2 Provides generic security measurement functions for DXE module.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Protocol/LoadFile.h>
11 #include <Library/DebugLib.h>
12 #include <Library/DxeServicesLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 #include <Library/SecurityManagementLib.h>
15 #include <Library/DevicePathLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
18 #define SECURITY_HANDLER_TABLE_SIZE 0x10
21 // Secruity Operation on Image and none Image.
23 #define EFI_AUTH_IMAGE_OPERATION_MASK (EFI_AUTH_OPERATION_VERIFY_IMAGE \
24 | EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD \
25 | EFI_AUTH_OPERATION_MEASURE_IMAGE)
26 #define EFI_AUTH_NONE_IMAGE_OPERATION_MASK (EFI_AUTH_OPERATION_CONNECT_POLICY \
27 | EFI_AUTH_OPERATION_AUTHENTICATION_STATE)
30 UINT32 SecurityOperation
;
31 SECURITY_FILE_AUTHENTICATION_STATE_HANDLER SecurityHandler
;
35 UINT32 Security2Operation
;
36 SECURITY2_FILE_AUTHENTICATION_HANDLER Security2Handler
;
39 UINT32 mCurrentAuthOperation
= 0;
40 UINT32 mNumberOfSecurityHandler
= 0;
41 UINT32 mMaxNumberOfSecurityHandler
= 0;
42 SECURITY_INFO
*mSecurityTable
= NULL
;
44 UINT32 mCurrentAuthOperation2
= 0;
45 UINT32 mNumberOfSecurity2Handler
= 0;
46 UINT32 mMaxNumberOfSecurity2Handler
= 0;
47 SECURITY2_INFO
*mSecurity2Table
= NULL
;
50 Reallocates more global memory to store the registered Handler list.
52 @retval RETURN_SUCCESS Reallocate memory successfully.
53 @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
57 ReallocateSecurityHandlerTable (
62 // Reallocate memory for security info structure.
64 mSecurityTable
= ReallocatePool (
65 mMaxNumberOfSecurityHandler
* sizeof (SECURITY_INFO
),
66 (mMaxNumberOfSecurityHandler
+ SECURITY_HANDLER_TABLE_SIZE
) * sizeof (SECURITY_INFO
),
71 // No enough resource is allocated.
73 if (mSecurityTable
== NULL
) {
74 return RETURN_OUT_OF_RESOURCES
;
78 // Increase max handler number
80 mMaxNumberOfSecurityHandler
= mMaxNumberOfSecurityHandler
+ SECURITY_HANDLER_TABLE_SIZE
;
81 return RETURN_SUCCESS
;
85 Check whether an operation is valid according to the requirement of current operation,
86 which must make sure that the measure image operation is the last one.
88 @param CurrentAuthOperation Current operation.
89 @param CheckAuthOperation Operation to be checked.
91 @retval TRUE Operation is valid for current operation.
92 @retval FALSE Operation is invalid for current operation.
95 CheckAuthenticationOperation (
96 IN UINT32 CurrentAuthOperation
,
97 IN UINT32 CheckAuthOperation
101 // Make sure new auth operation can be recognized.
103 ASSERT ((CheckAuthOperation
& ~(EFI_AUTH_IMAGE_OPERATION_MASK
| EFI_AUTH_OPERATION_AUTHENTICATION_STATE
| EFI_AUTH_OPERATION_IMAGE_REQUIRED
)) == 0);
106 // When current operation includes measure image operation,
107 // only another measure image operation or none operation will be allowed.
109 if ((CurrentAuthOperation
& EFI_AUTH_OPERATION_MEASURE_IMAGE
) == EFI_AUTH_OPERATION_MEASURE_IMAGE
) {
110 if (((CheckAuthOperation
& EFI_AUTH_OPERATION_MEASURE_IMAGE
) == EFI_AUTH_OPERATION_MEASURE_IMAGE
) ||
111 ((CheckAuthOperation
& EFI_AUTH_IMAGE_OPERATION_MASK
) == EFI_AUTH_OPERATION_NONE
))
120 // When current operation doesn't include measure image operation,
121 // any new operation will be allowed.
127 Register security measurement handler with its operation type. The different
128 handler with the same operation can all be registered.
130 If SecurityHandler is NULL, then ASSERT().
131 If no enough resources available to register new handler, then ASSERT().
132 If AuthenticationOperation is not recongnized, then ASSERT().
133 If the previous register handler can't be executed before the later register handler, then ASSERT().
135 @param[in] SecurityHandler Security measurement service handler to be registered.
136 @param[in] AuthenticationOperation Operation type is specified for the registered handler.
138 @retval EFI_SUCCESS The handlers were registered successfully.
142 RegisterSecurityHandler (
143 IN SECURITY_FILE_AUTHENTICATION_STATE_HANDLER SecurityHandler
,
144 IN UINT32 AuthenticationOperation
149 ASSERT (SecurityHandler
!= NULL
);
152 // Make sure AuthenticationOperation is valid in the register order.
154 ASSERT (CheckAuthenticationOperation (mCurrentAuthOperation
, AuthenticationOperation
));
155 mCurrentAuthOperation
= mCurrentAuthOperation
| AuthenticationOperation
;
158 // Check whether the handler lists is enough to store new handler.
160 if (mNumberOfSecurityHandler
== mMaxNumberOfSecurityHandler
) {
162 // Allocate more resources for new handler.
164 Status
= ReallocateSecurityHandlerTable ();
165 ASSERT_EFI_ERROR (Status
);
169 // Register new handler into the handler list.
171 mSecurityTable
[mNumberOfSecurityHandler
].SecurityOperation
= AuthenticationOperation
;
172 mSecurityTable
[mNumberOfSecurityHandler
].SecurityHandler
= SecurityHandler
;
173 mNumberOfSecurityHandler
++;
179 Execute registered handlers until one returns an error and that error is returned.
180 If none of the handlers return an error, then EFI_SUCCESS is returned.
182 Before exectue handler, get the image buffer by file device path if a handler
183 requires the image file. And return the image buffer to each handler when exectue handler.
185 The handlers are executed in same order to their registered order.
187 @param[in] AuthenticationStatus
188 This is the authentication type returned from the Section
189 Extraction protocol. See the Section Extraction Protocol
190 Specification for details on this type.
191 @param[in] FilePath This is a pointer to the device path of the file that is
192 being dispatched. This will optionally be used for logging.
194 @retval EFI_SUCCESS The file specified by File did authenticate when more
195 than one security handler services were registered,
196 or the file did not authenticate when no security
197 handler service was registered. And the platform policy
198 dictates that the DXE Core may use File.
199 @retval EFI_INVALID_PARAMETER File is NULL.
200 @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
201 the platform policy dictates that File should be placed
202 in the untrusted state. A file may be promoted from
203 the untrusted to the trusted state at a future time
204 with a call to the Trust() DXE Service.
205 @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
206 the platform policy dictates that File should not be
207 used for any purpose.
211 ExecuteSecurityHandlers (
212 IN UINT32 AuthenticationStatus
,
213 IN CONST EFI_DEVICE_PATH_PROTOCOL
*FilePath
218 UINT32 HandlerAuthenticationStatus
;
222 EFI_DEVICE_PATH_PROTOCOL
*Node
;
223 EFI_DEVICE_PATH_PROTOCOL
*FilePathToVerfiy
;
225 if (FilePath
== NULL
) {
226 return EFI_INVALID_PARAMETER
;
230 // Directly return successfully when no handler is registered.
232 if (mNumberOfSecurityHandler
== 0) {
236 Status
= EFI_SUCCESS
;
239 HandlerAuthenticationStatus
= AuthenticationStatus
;
240 FilePathToVerfiy
= (EFI_DEVICE_PATH_PROTOCOL
*)FilePath
;
242 // Run security handler in same order to their registered list
244 for (Index
= 0; Index
< mNumberOfSecurityHandler
; Index
++) {
245 if ((mSecurityTable
[Index
].SecurityOperation
& EFI_AUTH_OPERATION_IMAGE_REQUIRED
) == EFI_AUTH_OPERATION_IMAGE_REQUIRED
) {
247 // Try get file buffer when the handler requires image buffer.
249 if (FileBuffer
== NULL
) {
250 Node
= FilePathToVerfiy
;
251 Status
= gBS
->LocateDevicePath (&gEfiLoadFileProtocolGuid
, &Node
, &Handle
);
253 // Try to get image by FALSE boot policy for the exact boot file path.
255 FileBuffer
= GetFileBufferByFilePath (FALSE
, FilePath
, &FileSize
, &AuthenticationStatus
);
256 if (FileBuffer
== NULL
) {
258 // Try to get image by TRUE boot policy for the inexact boot file path.
260 FileBuffer
= GetFileBufferByFilePath (TRUE
, FilePath
, &FileSize
, &AuthenticationStatus
);
263 if ((FileBuffer
!= NULL
) && (!EFI_ERROR (Status
))) {
265 // LoadFile () may cause the device path of the Handle be updated.
267 FilePathToVerfiy
= AppendDevicePath (DevicePathFromHandle (Handle
), Node
);
272 Status
= mSecurityTable
[Index
].SecurityHandler (
273 HandlerAuthenticationStatus
,
278 if (EFI_ERROR (Status
)) {
283 if (FileBuffer
!= NULL
) {
284 FreePool (FileBuffer
);
287 if (FilePathToVerfiy
!= FilePath
) {
288 FreePool (FilePathToVerfiy
);
295 Reallocates more global memory to store the registered Securit2Handler list.
297 @retval RETURN_SUCCESS Reallocate memory successfully.
298 @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
302 ReallocateSecurity2HandlerTable (
307 // Reallocate memory for security info structure.
309 mSecurity2Table
= ReallocatePool (
310 mMaxNumberOfSecurity2Handler
* sizeof (SECURITY2_INFO
),
311 (mMaxNumberOfSecurity2Handler
+ SECURITY_HANDLER_TABLE_SIZE
) * sizeof (SECURITY2_INFO
),
316 // No enough resource is allocated.
318 if (mSecurity2Table
== NULL
) {
319 return RETURN_OUT_OF_RESOURCES
;
323 // Increase max handler number
325 mMaxNumberOfSecurity2Handler
= mMaxNumberOfSecurity2Handler
+ SECURITY_HANDLER_TABLE_SIZE
;
326 return RETURN_SUCCESS
;
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.
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.
338 @param CurrentAuthOperation Current operation.
339 @param CheckAuthOperation Operation to be checked.
341 @retval TRUE Operation is valid for current operation.
342 @retval FALSE Operation is invalid for current operation.
345 CheckAuthentication2Operation (
346 IN UINT32 CurrentAuthOperation
,
347 IN UINT32 CheckAuthOperation
351 // Make sure new auth operation can be recognized.
353 if (CheckAuthOperation
== EFI_AUTH_OPERATION_NONE
) {
357 if ((CheckAuthOperation
& ~(EFI_AUTH_IMAGE_OPERATION_MASK
|
358 EFI_AUTH_NONE_IMAGE_OPERATION_MASK
|
359 EFI_AUTH_OPERATION_IMAGE_REQUIRED
)) != 0)
365 // When current operation includes measure image operation,
366 // only another measure image or none image operation will be allowed.
368 if ((CurrentAuthOperation
& EFI_AUTH_OPERATION_MEASURE_IMAGE
) == EFI_AUTH_OPERATION_MEASURE_IMAGE
) {
369 if (((CheckAuthOperation
& EFI_AUTH_OPERATION_MEASURE_IMAGE
) == EFI_AUTH_OPERATION_MEASURE_IMAGE
) ||
370 ((CheckAuthOperation
& EFI_AUTH_IMAGE_OPERATION_MASK
) == 0))
379 // Any other operation will be allowed.
385 Register security measurement handler with its operation type. Different
386 handlers with the same operation can all be registered.
388 If Security2Handler is NULL, then ASSERT().
389 If no enough resources available to register new handler, then ASSERT().
390 If AuthenticationOperation is not recongnized, then ASSERT().
391 If AuthenticationOperation is EFI_AUTH_OPERATION_NONE, then ASSERT().
392 If the previous register handler can't be executed before the later register handler, then ASSERT().
394 @param[in] Security2Handler The security measurement service handler to be registered.
395 @param[in] AuthenticationOperation The operation type is specified for the registered handler.
397 @retval EFI_SUCCESS The handlers were registered successfully.
401 RegisterSecurity2Handler (
402 IN SECURITY2_FILE_AUTHENTICATION_HANDLER Security2Handler
,
403 IN UINT32 AuthenticationOperation
408 ASSERT (Security2Handler
!= NULL
);
411 // Make sure AuthenticationOperation is valid in the register order.
413 ASSERT (CheckAuthentication2Operation (mCurrentAuthOperation2
, AuthenticationOperation
));
414 mCurrentAuthOperation2
= mCurrentAuthOperation2
| AuthenticationOperation
;
417 // Check whether the handler lists is enough to store new handler.
419 if (mNumberOfSecurity2Handler
== mMaxNumberOfSecurity2Handler
) {
421 // Allocate more resources for new handler.
423 Status
= ReallocateSecurity2HandlerTable ();
424 ASSERT_EFI_ERROR (Status
);
428 // Register new handler into the handler list.
430 mSecurity2Table
[mNumberOfSecurity2Handler
].Security2Operation
= AuthenticationOperation
;
431 mSecurity2Table
[mNumberOfSecurity2Handler
].Security2Handler
= Security2Handler
;
432 mNumberOfSecurity2Handler
++;
438 Execute registered handlers based on input AuthenticationOperation until
439 one returns an error and that error is returned.
441 If none of the handlers return an error, then EFI_SUCCESS is returned.
442 The handlers those satisfy AuthenticationOperation will only be executed.
443 The handlers are executed in same order to their registered order.
445 @param[in] AuthenticationOperation
446 The operation type specifies which handlers will be executed.
447 @param[in] AuthenticationStatus
448 The authentication status for the input file.
449 @param[in] File This is a pointer to the device path of the file that is
450 being dispatched. This will optionally be used for logging.
451 @param[in] FileBuffer A pointer to the buffer with the UEFI file image
452 @param[in] FileSize The size of File buffer.
453 @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.
455 @retval EFI_SUCCESS The file specified by DevicePath and non-NULL
456 FileBuffer did authenticate, and the platform policy dictates
457 that the DXE Foundation may use the file.
458 @retval EFI_SUCCESS The device path specified by NULL device path DevicePath
459 and non-NULL FileBuffer did authenticate, and the platform
460 policy dictates that the DXE Foundation may execute the image in
462 @retval EFI_SUCCESS FileBuffer is NULL and current user has permission to start
463 UEFI device drivers on the device path specified by DevicePath.
464 @retval EFI_SECURITY_VIOLATION The file specified by File or FileBuffer did not
465 authenticate, and the platform policy dictates that
466 the file should be placed in the untrusted state.
467 @retval EFI_SECURITY_VIOLATION FileBuffer FileBuffer is NULL and the user has no
468 permission to start UEFI device drivers on the device path specified
470 @retval EFI_SECURITY_VIOLATION FileBuffer is not NULL and the user has no permission to load
471 drivers from the device path specified by DevicePath. The
472 image has been added into the list of the deferred images.
473 @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
474 the platform policy dictates that the DXE
475 Foundation may not use File.
476 @retval EFI_INVALID_PARAMETER File and FileBuffer are both NULL.
480 ExecuteSecurity2Handlers (
481 IN UINT32 AuthenticationOperation
,
482 IN UINT32 AuthenticationStatus
,
483 IN CONST EFI_DEVICE_PATH_PROTOCOL
*File OPTIONAL
,
486 IN BOOLEAN BootPolicy
493 // Invalid case if File and FileBuffer are both NULL.
495 if ((File
== NULL
) && (FileBuffer
== NULL
)) {
496 return EFI_INVALID_PARAMETER
;
500 // Directly return successfully when no handler is registered.
502 if (mNumberOfSecurity2Handler
== 0) {
507 // Run security handler in same order to their registered list
509 for (Index
= 0; Index
< mNumberOfSecurity2Handler
; Index
++) {
511 // If FileBuffer is not NULL, the input is Image, which will be handled by EFI_AUTH_IMAGE_OPERATION_MASK operation.
512 // If FileBuffer is NULL, the input is not Image, which will be handled by EFI_AUTH_NONE_IMAGE_OPERATION_MASK operation.
513 // Other cases are ignored.
515 if (((FileBuffer
!= NULL
) && ((mSecurity2Table
[Index
].Security2Operation
& EFI_AUTH_IMAGE_OPERATION_MASK
) != 0)) ||
516 ((FileBuffer
== NULL
) && ((mSecurity2Table
[Index
].Security2Operation
& EFI_AUTH_NONE_IMAGE_OPERATION_MASK
) != 0)))
519 // Execute registered handlers based on input AuthenticationOperation
521 if ((mSecurity2Table
[Index
].Security2Operation
& AuthenticationOperation
) != 0) {
522 Status
= mSecurity2Table
[Index
].Security2Handler (
523 AuthenticationStatus
,
529 if (EFI_ERROR (Status
)) {