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