]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.c
Add new SecurityManagementLib, and update SecurityStub driver to use this lib.
[mirror_edk2.git] / MdeModulePkg / Library / DxeSecurityManagementLib / DxeSecurityManagementLib.c
diff --git a/MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.c b/MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.c
new file mode 100644 (file)
index 0000000..1ff1bf6
--- /dev/null
@@ -0,0 +1,251 @@
+/** @file\r
+  Provides generic security measurement functions for DXE module.\r
+\r
+Copyright (c) 2009 Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/SecurityManagementLib.h>\r
+\r
+#define SECURITY_HANDLER_TABLE_SIZE   0x10\r
+\r
+#define EFI_AUTH_OPERATION_MASK       EFI_AUTH_OPERATION_VERIFY_IMAGE \\r
+                                      | EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD \\r
+                                      | EFI_AUTH_OPERATION_MEASURE_IMAGE\r
+\r
+typedef struct {\r
+  UINT32  SecurityOperation;\r
+  SECURITY_FILE_AUTHENTICATION_STATE_HANDLER  SecurityHandler;\r
+} SECURITY_INFO;\r
+\r
+UINT32  mCurrentAuthOperation       = 0;\r
+UINT32  mNumberOfSecurityHandler    = 0;\r
+UINT32  mMaxNumberOfSecurityHandler = 0;\r
+SECURITY_INFO  *mSecurityTable      = NULL;\r
+\r
+/**\r
+  Reallocates more global memory to store the registered Handler list.\r
+\r
+  @retval  RETURN_SUCCESS            Reallocate memory successfully.\r
+  @retval  RETURN_OUT_OF_RESOURCES   No enough memory to allocated.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+ReallocateSecurityHandlerTable (\r
+  )\r
+{\r
+  //\r
+  // Reallocate memory for security info structure.\r
+  //\r
+  mSecurityTable = ReallocatePool (\r
+                     mMaxNumberOfSecurityHandler * sizeof (SECURITY_INFO), \r
+                     (mMaxNumberOfSecurityHandler + SECURITY_HANDLER_TABLE_SIZE) * sizeof (SECURITY_INFO), \r
+                     mSecurityTable\r
+                     );\r
+\r
+  //\r
+  // No enough resource is allocated.\r
+  //\r
+  if (mSecurityTable == NULL) {\r
+    return RETURN_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Increase max handler number\r
+  //\r
+  mMaxNumberOfSecurityHandler = mMaxNumberOfSecurityHandler + SECURITY_HANDLER_TABLE_SIZE;\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Check whether an operation is valid according to the requirement of current operation, \r
+ which must make sure that the measure image operation is the last one.\r
+\r
+ @param CurrentAuthOperation  Current operation.\r
+ @param CheckAuthOperation    Operation to be checked.\r
+\r
+ @retval  TRUE   Operation is valid for current operation.\r
+ @retval  FALSE  Operation is invalid for current operation.\r
+**/\r
+BOOLEAN\r
+CheckAuthenticationOperation (\r
+  IN  UINT32    CurrentAuthOperation,\r
+  IN  UINT32    CheckAuthOperation\r
+  )\r
+{ \r
+  //\r
+  // Make sure new auth operation can be recognized.\r
+  //\r
+  ASSERT ((CheckAuthOperation & ~(EFI_AUTH_OPERATION_MASK | EFI_AUTH_OPERATION_IMAGE_REQUIRED)) == 0);\r
+  \r
+  //\r
+  // When current operation includes measure image operation, \r
+  // only another measure image operation or none operation will be allowed.\r
+  //\r
+  if ((CurrentAuthOperation & EFI_AUTH_OPERATION_MEASURE_IMAGE) == EFI_AUTH_OPERATION_MEASURE_IMAGE) {\r
+    if (((CheckAuthOperation & EFI_AUTH_OPERATION_MEASURE_IMAGE) == EFI_AUTH_OPERATION_MEASURE_IMAGE) ||\r
+        ((CheckAuthOperation & EFI_AUTH_OPERATION_MASK) == EFI_AUTH_OPERATION_NONE)) {\r
+      return TRUE;\r
+    } else {\r
+      return FALSE;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // When current operation doesn't include measure image operation, \r
+  // any new operation will be allowed.\r
+  //\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Register security measurement handler with its operation type. The different\r
+  handler with the same operation can all be registered.\r
+\r
+  If SecurityHandler is NULL, then ASSERT().\r
+  If no enough resources available to register new handler, then ASSERT().\r
+  If AuthenticationOperation is not recongnized, then ASSERT().\r
+  If the previous register handler can't be executed before the later register handler, then ASSERT().\r
+\r
+  @param[in]  SecurityHandler           Security measurement service handler to be registered.\r
+  @param[in]  AuthenticationOperation   Operation type is specified for the registered handler.\r
+\r
+  @retval EFI_SUCCESS              The handlers were registered successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterSecurityHandler (\r
+  IN  SECURITY_FILE_AUTHENTICATION_STATE_HANDLER  SecurityHandler,\r
+  IN  UINT32                                      AuthenticationOperation\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  ASSERT (SecurityHandler != NULL);\r
+\r
+  //\r
+  // Make sure AuthenticationOperation is valid in the register order.\r
+  //\r
+  ASSERT (CheckAuthenticationOperation (mCurrentAuthOperation, AuthenticationOperation));\r
+  mCurrentAuthOperation = mCurrentAuthOperation | AuthenticationOperation;\r
+\r
+  //\r
+  // Check whether the handler lists is enough to store new handler.\r
+  //\r
+  if (mNumberOfSecurityHandler == mMaxNumberOfSecurityHandler) {\r
+    //\r
+    // Allocate more resources for new handler.\r
+    //\r
+    Status = ReallocateSecurityHandlerTable();\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  //\r
+  // Register new handler into the handler list.\r
+  //\r
+  mSecurityTable[mNumberOfSecurityHandler].SecurityOperation = AuthenticationOperation;\r
+  mSecurityTable[mNumberOfSecurityHandler].SecurityHandler   = SecurityHandler;\r
+  mNumberOfSecurityHandler ++;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Execute registered handlers until one returns an error and that error is returned.\r
+  If none of the handlers return an error, then EFI_SUCCESS is returned.\r
+\r
+  Before exectue handler, get the image buffer by file device path if a handler \r
+  requires the image file. And return the image buffer to each handler when exectue handler.\r
+\r
+  The handlers are executed in same order to their registered order.\r
+\r
+  @param[in]  AuthenticationStatus \r
+                           This is the authentication type returned from the Section\r
+                           Extraction protocol. See the Section Extraction Protocol\r
+                           Specification for details on this type.\r
+  @param[in]  FilePath     This is a pointer to the device path of the file that is\r
+                           being dispatched. This will optionally be used for logging.\r
+\r
+  @retval EFI_SUCCESS            The file specified by File did authenticate when more\r
+                                 than one security handler services were registered, \r
+                                 or the file did not authenticate when no security \r
+                                 handler service was registered. And the platform policy \r
+                                 dictates that the DXE Core may use File.\r
+  @retval EFI_INVALID_PARAMETER  File is NULL.\r
+  @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and\r
+                                 the platform policy dictates that File should be placed\r
+                                 in the untrusted state. A file may be promoted from\r
+                                 the untrusted to the trusted state at a future time\r
+                                 with a call to the Trust() DXE Service.\r
+  @retval EFI_ACCESS_DENIED      The file specified by File did not authenticate, and\r
+                                 the platform policy dictates that File should not be\r
+                                 used for any purpose.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExecuteSecurityHandlers (\r
+  IN  UINT32                            AuthenticationStatus,\r
+  IN  CONST EFI_DEVICE_PATH_PROTOCOL    *FilePath\r
+  )\r
+{\r
+  UINT32        Index;\r
+  EFI_STATUS    Status;\r
+  UINT32        HandlerAuthenticationStatus;\r
+  VOID          *FileBuffer;\r
+  UINTN         FileSize;\r
+  \r
+  if (FilePath == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Directly return successfully when no handler is registered.\r
+  //\r
+  if (mNumberOfSecurityHandler == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  Status                      = EFI_SUCCESS;\r
+  FileBuffer                  = NULL;\r
+  FileSize                    = 0;\r
+  HandlerAuthenticationStatus = AuthenticationStatus;\r
+  //\r
+  // Run security handler in same order to their registered list\r
+  //\r
+  for (Index = 0; Index < mNumberOfSecurityHandler; Index ++) {\r
+    if ((mSecurityTable[Index].SecurityOperation & EFI_AUTH_OPERATION_IMAGE_REQUIRED) == EFI_AUTH_OPERATION_IMAGE_REQUIRED) {\r
+      //\r
+      // Try get file buffer when the handler requires image buffer.\r
+      //\r
+      if (FileBuffer == NULL) {\r
+        FileBuffer = GetFileBufferByFilePath (FALSE, FilePath, &FileSize, &AuthenticationStatus);\r
+      }\r
+    }\r
+    Status = mSecurityTable[Index].SecurityHandler (\r
+               HandlerAuthenticationStatus,\r
+               FilePath,\r
+               FileBuffer,\r
+               FileSize\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (FileBuffer != NULL) {\r
+    FreePool (FileBuffer);\r
+  }\r
+\r
+  return Status;\r
+}\r