]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Library / DxeSecurityManagementLib / DxeSecurityManagementLib.c
1 /** @file
2 Provides generic security measurement functions for DXE module.
3
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <PiDxe.h>
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>
17
18 #define SECURITY_HANDLER_TABLE_SIZE 0x10
19
20 //
21 // Secruity Operation on Image and none Image.
22 //
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)
28
29 typedef struct {
30 UINT32 SecurityOperation;
31 SECURITY_FILE_AUTHENTICATION_STATE_HANDLER SecurityHandler;
32 } SECURITY_INFO;
33
34 typedef struct {
35 UINT32 Security2Operation;
36 SECURITY2_FILE_AUTHENTICATION_HANDLER Security2Handler;
37 } SECURITY2_INFO;
38
39 UINT32 mCurrentAuthOperation = 0;
40 UINT32 mNumberOfSecurityHandler = 0;
41 UINT32 mMaxNumberOfSecurityHandler = 0;
42 SECURITY_INFO *mSecurityTable = NULL;
43
44 UINT32 mCurrentAuthOperation2 = 0;
45 UINT32 mNumberOfSecurity2Handler = 0;
46 UINT32 mMaxNumberOfSecurity2Handler = 0;
47 SECURITY2_INFO *mSecurity2Table = NULL;
48
49 /**
50 Reallocates more global memory to store the registered Handler list.
51
52 @retval RETURN_SUCCESS Reallocate memory successfully.
53 @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
54 **/
55 RETURN_STATUS
56 EFIAPI
57 ReallocateSecurityHandlerTable (
58 VOID
59 )
60 {
61 //
62 // Reallocate memory for security info structure.
63 //
64 mSecurityTable = ReallocatePool (
65 mMaxNumberOfSecurityHandler * sizeof (SECURITY_INFO),
66 (mMaxNumberOfSecurityHandler + SECURITY_HANDLER_TABLE_SIZE) * sizeof (SECURITY_INFO),
67 mSecurityTable
68 );
69
70 //
71 // No enough resource is allocated.
72 //
73 if (mSecurityTable == NULL) {
74 return RETURN_OUT_OF_RESOURCES;
75 }
76
77 //
78 // Increase max handler number
79 //
80 mMaxNumberOfSecurityHandler = mMaxNumberOfSecurityHandler + SECURITY_HANDLER_TABLE_SIZE;
81 return RETURN_SUCCESS;
82 }
83
84 /**
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.
87
88 @param CurrentAuthOperation Current operation.
89 @param CheckAuthOperation Operation to be checked.
90
91 @retval TRUE Operation is valid for current operation.
92 @retval FALSE Operation is invalid for current operation.
93 **/
94 BOOLEAN
95 CheckAuthenticationOperation (
96 IN UINT32 CurrentAuthOperation,
97 IN UINT32 CheckAuthOperation
98 )
99 {
100 //
101 // Make sure new auth operation can be recognized.
102 //
103 ASSERT ((CheckAuthOperation & ~(EFI_AUTH_IMAGE_OPERATION_MASK | EFI_AUTH_OPERATION_AUTHENTICATION_STATE | EFI_AUTH_OPERATION_IMAGE_REQUIRED)) == 0);
104
105 //
106 // When current operation includes measure image operation,
107 // only another measure image operation or none operation will be allowed.
108 //
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))
112 {
113 return TRUE;
114 } else {
115 return FALSE;
116 }
117 }
118
119 //
120 // When current operation doesn't include measure image operation,
121 // any new operation will be allowed.
122 //
123 return TRUE;
124 }
125
126 /**
127 Register security measurement handler with its operation type. The different
128 handler with the same operation can all be registered.
129
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().
134
135 @param[in] SecurityHandler Security measurement service handler to be registered.
136 @param[in] AuthenticationOperation Operation type is specified for the registered handler.
137
138 @retval EFI_SUCCESS The handlers were registered successfully.
139 **/
140 EFI_STATUS
141 EFIAPI
142 RegisterSecurityHandler (
143 IN SECURITY_FILE_AUTHENTICATION_STATE_HANDLER SecurityHandler,
144 IN UINT32 AuthenticationOperation
145 )
146 {
147 EFI_STATUS Status;
148
149 ASSERT (SecurityHandler != NULL);
150
151 //
152 // Make sure AuthenticationOperation is valid in the register order.
153 //
154 ASSERT (CheckAuthenticationOperation (mCurrentAuthOperation, AuthenticationOperation));
155 mCurrentAuthOperation = mCurrentAuthOperation | AuthenticationOperation;
156
157 //
158 // Check whether the handler lists is enough to store new handler.
159 //
160 if (mNumberOfSecurityHandler == mMaxNumberOfSecurityHandler) {
161 //
162 // Allocate more resources for new handler.
163 //
164 Status = ReallocateSecurityHandlerTable ();
165 ASSERT_EFI_ERROR (Status);
166 }
167
168 //
169 // Register new handler into the handler list.
170 //
171 mSecurityTable[mNumberOfSecurityHandler].SecurityOperation = AuthenticationOperation;
172 mSecurityTable[mNumberOfSecurityHandler].SecurityHandler = SecurityHandler;
173 mNumberOfSecurityHandler++;
174
175 return EFI_SUCCESS;
176 }
177
178 /**
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.
181
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.
184
185 The handlers are executed in same order to their registered order.
186
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.
193
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.
208 **/
209 EFI_STATUS
210 EFIAPI
211 ExecuteSecurityHandlers (
212 IN UINT32 AuthenticationStatus,
213 IN CONST EFI_DEVICE_PATH_PROTOCOL *FilePath
214 )
215 {
216 UINT32 Index;
217 EFI_STATUS Status;
218 UINT32 HandlerAuthenticationStatus;
219 VOID *FileBuffer;
220 UINTN FileSize;
221 EFI_HANDLE Handle;
222 EFI_DEVICE_PATH_PROTOCOL *Node;
223 EFI_DEVICE_PATH_PROTOCOL *FilePathToVerfiy;
224
225 if (FilePath == NULL) {
226 return EFI_INVALID_PARAMETER;
227 }
228
229 //
230 // Directly return successfully when no handler is registered.
231 //
232 if (mNumberOfSecurityHandler == 0) {
233 return EFI_SUCCESS;
234 }
235
236 Status = EFI_SUCCESS;
237 FileBuffer = NULL;
238 FileSize = 0;
239 HandlerAuthenticationStatus = AuthenticationStatus;
240 FilePathToVerfiy = (EFI_DEVICE_PATH_PROTOCOL *)FilePath;
241 //
242 // Run security handler in same order to their registered list
243 //
244 for (Index = 0; Index < mNumberOfSecurityHandler; Index++) {
245 if ((mSecurityTable[Index].SecurityOperation & EFI_AUTH_OPERATION_IMAGE_REQUIRED) == EFI_AUTH_OPERATION_IMAGE_REQUIRED) {
246 //
247 // Try get file buffer when the handler requires image buffer.
248 //
249 if (FileBuffer == NULL) {
250 Node = FilePathToVerfiy;
251 Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);
252 //
253 // Try to get image by FALSE boot policy for the exact boot file path.
254 //
255 FileBuffer = GetFileBufferByFilePath (FALSE, FilePath, &FileSize, &AuthenticationStatus);
256 if (FileBuffer == NULL) {
257 //
258 // Try to get image by TRUE boot policy for the inexact boot file path.
259 //
260 FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, &FileSize, &AuthenticationStatus);
261 }
262
263 if ((FileBuffer != NULL) && (!EFI_ERROR (Status))) {
264 //
265 // LoadFile () may cause the device path of the Handle be updated.
266 //
267 FilePathToVerfiy = AppendDevicePath (DevicePathFromHandle (Handle), Node);
268 }
269 }
270 }
271
272 Status = mSecurityTable[Index].SecurityHandler (
273 HandlerAuthenticationStatus,
274 FilePathToVerfiy,
275 FileBuffer,
276 FileSize
277 );
278 if (EFI_ERROR (Status)) {
279 break;
280 }
281 }
282
283 if (FileBuffer != NULL) {
284 FreePool (FileBuffer);
285 }
286
287 if (FilePathToVerfiy != FilePath) {
288 FreePool (FilePathToVerfiy);
289 }
290
291 return Status;
292 }
293
294 /**
295 Reallocates more global memory to store the registered Securit2Handler list.
296
297 @retval RETURN_SUCCESS Reallocate memory successfully.
298 @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
299 **/
300 RETURN_STATUS
301 EFIAPI
302 ReallocateSecurity2HandlerTable (
303 VOID
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
357 if ((CheckAuthOperation & ~(EFI_AUTH_IMAGE_OPERATION_MASK |
358 EFI_AUTH_NONE_IMAGE_OPERATION_MASK |
359 EFI_AUTH_OPERATION_IMAGE_REQUIRED)) != 0)
360 {
361 return FALSE;
362 }
363
364 //
365 // When current operation includes measure image operation,
366 // only another measure image or none image operation will be allowed.
367 //
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))
371 {
372 return TRUE;
373 } else {
374 return FALSE;
375 }
376 }
377
378 //
379 // Any other operation will be allowed.
380 //
381 return TRUE;
382 }
383
384 /**
385 Register security measurement handler with its operation type. Different
386 handlers with the same operation can all be registered.
387
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().
393
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.
396
397 @retval EFI_SUCCESS The handlers were registered successfully.
398 **/
399 EFI_STATUS
400 EFIAPI
401 RegisterSecurity2Handler (
402 IN SECURITY2_FILE_AUTHENTICATION_HANDLER Security2Handler,
403 IN UINT32 AuthenticationOperation
404 )
405 {
406 EFI_STATUS Status;
407
408 ASSERT (Security2Handler != NULL);
409
410 //
411 // Make sure AuthenticationOperation is valid in the register order.
412 //
413 ASSERT (CheckAuthentication2Operation (mCurrentAuthOperation2, AuthenticationOperation));
414 mCurrentAuthOperation2 = mCurrentAuthOperation2 | AuthenticationOperation;
415
416 //
417 // Check whether the handler lists is enough to store new handler.
418 //
419 if (mNumberOfSecurity2Handler == mMaxNumberOfSecurity2Handler) {
420 //
421 // Allocate more resources for new handler.
422 //
423 Status = ReallocateSecurity2HandlerTable ();
424 ASSERT_EFI_ERROR (Status);
425 }
426
427 //
428 // Register new handler into the handler list.
429 //
430 mSecurity2Table[mNumberOfSecurity2Handler].Security2Operation = AuthenticationOperation;
431 mSecurity2Table[mNumberOfSecurity2Handler].Security2Handler = Security2Handler;
432 mNumberOfSecurity2Handler++;
433
434 return EFI_SUCCESS;
435 }
436
437 /**
438 Execute registered handlers based on input AuthenticationOperation until
439 one returns an error and that error is returned.
440
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.
444
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.
454
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
461 FileBuffer.
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
469 by DevicePath.
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.
477 **/
478 EFI_STATUS
479 EFIAPI
480 ExecuteSecurity2Handlers (
481 IN UINT32 AuthenticationOperation,
482 IN UINT32 AuthenticationStatus,
483 IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,
484 IN VOID *FileBuffer,
485 IN UINTN FileSize,
486 IN BOOLEAN BootPolicy
487 )
488 {
489 UINT32 Index;
490 EFI_STATUS Status;
491
492 //
493 // Invalid case if File and FileBuffer are both NULL.
494 //
495 if ((File == NULL) && (FileBuffer == NULL)) {
496 return EFI_INVALID_PARAMETER;
497 }
498
499 //
500 // Directly return successfully when no handler is registered.
501 //
502 if (mNumberOfSecurity2Handler == 0) {
503 return EFI_SUCCESS;
504 }
505
506 //
507 // Run security handler in same order to their registered list
508 //
509 for (Index = 0; Index < mNumberOfSecurity2Handler; Index++) {
510 //
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.
514 //
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)))
517 {
518 //
519 // Execute registered handlers based on input AuthenticationOperation
520 //
521 if ((mSecurity2Table[Index].Security2Operation & AuthenticationOperation) != 0) {
522 Status = mSecurity2Table[Index].Security2Handler (
523 AuthenticationStatus,
524 File,
525 FileBuffer,
526 FileSize,
527 BootPolicy
528 );
529 if (EFI_ERROR (Status)) {
530 return Status;
531 }
532 }
533 }
534 }
535
536 return EFI_SUCCESS;
537 }