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