]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Update common authenticated variable (non PK/KEK/DB/DBX) support to comply with lates...
authortye1 <tye1@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 31 Mar 2012 04:42:20 +0000 (04:42 +0000)
committertye1 <tye1@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 31 Mar 2012 04:42:20 +0000 (04:42 +0000)
Signed-off by: tye1
Reviewed-by: geekboy15a
Reviewed-by: sfu5
Reviewed-by: gdong1
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13157 6f19259b-4bc3-4df7-8a09-765794883524

SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h
SecurityPkg/SecurityPkg.dec
SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf

index 7e543ee9116cdd1e735627be0aa1cb125f3ca517..f18f4aa7eb44eaa76b10e7ac44a16f84aa3c5bf6 100644 (file)
@@ -49,6 +49,15 @@ extern EFI_GUID gEfiCustomModeEnableGuid;
 #define CUSTOM_SECURE_BOOT_MODE       1\r
 #define STANDARD_SECURE_BOOT_MODE     0\r
 \r
+///\r
+/// "certdb" variable stores the signer's certificates for non PK/KEK/DB/DBX\r
+/// variables with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.\r
+/// \r
+///\r
+#define EFI_CERT_DB_NAME L"certdb"\r
+\r
+extern EFI_GUID gEfiCertDbGuid;\r
+\r
 ///\r
 /// Alignment of variable name and data, according to the architecture:\r
 /// * For IA-32 and Intel(R) 64 architectures: 1.\r
index e5471778ee21a6282139be8753732da98d7900c4..38e3c256192b55ebe923c82855b59d4c3bd3f930 100644 (file)
 [Guids]\r
   ## Security package token space guid\r
   # Include/Guid/SecurityPkgTokenSpace.h\r
-  gEfiSecurityPkgTokenSpaceGuid  = { 0xd3fb176, 0x9569, 0x4d51, { 0xa3, 0xef, 0x7d, 0x61, 0xc6, 0x4f, 0xea, 0xba }}\r
+  gEfiSecurityPkgTokenSpaceGuid      = { 0xd3fb176, 0x9569, 0x4d51, { 0xa3, 0xef, 0x7d, 0x61, 0xc6, 0x4f, 0xea, 0xba }}\r
   ## Guid acted as the authenticated variable store header's signature, and to specify the variable list entries put in the EFI system table.\r
   #  Include/Guid/AuthenticatedVariableFormat.h\r
-  gEfiAuthenticatedVariableGuid  = { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }\r
+  gEfiAuthenticatedVariableGuid      = { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }\r
 \r
   #  Include/Guid/AuthenticatedVariableFormat.h\r
-  gEfiSecureBootEnableDisableGuid = { 0xf0a30bc7, 0xaf08, 0x4556, { 0x99, 0xc4, 0x0, 0x10, 0x9, 0xc9, 0x3a, 0x44 } }\r
+  gEfiSecureBootEnableDisableGuid    = { 0xf0a30bc7, 0xaf08, 0x4556, { 0x99, 0xc4, 0x0, 0x10, 0x9, 0xc9, 0x3a, 0x44 } }\r
 \r
   #  Include/Guid/AuthenticatedVariableFormat.h\r
   gEfiCustomModeEnableGuid           = { 0xc076ec0c, 0x7028, 0x4399, { 0xa0, 0x72, 0x71, 0xee, 0x5c, 0x44, 0x8b, 0x9f } }\r
+\r
+  #  Include/Guid/AuthenticatedVariableFormat.h\r
+  gEfiCertDbGuid                     = { 0xd9bee56e, 0x75dc, 0x49d9, { 0xb4, 0xd7, 0xb5, 0x34, 0x21, 0xf, 0x63, 0x7a } }\r
   \r
   ## Include/Guid/TcgEventHob.h\r
   gTcgEventEntryHobGuid              = { 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 }}\r
index 4036885570a04c737fca4273ceb109c3361f10c7..12587af7b2db90f946dd3462a869d4475c1693b5 100644 (file)
@@ -164,6 +164,7 @@ AutenticatedVariableServiceInitialize (
   UINT8                   SecureBootMode;\r
   UINT8                   SecureBootEnable;\r
   UINT8                   CustomMode;\r
+  UINT32                  ListSize;\r
 \r
   //\r
   // Initialize hash context.\r
@@ -388,6 +389,36 @@ AutenticatedVariableServiceInitialize (
   \r
   DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME, CustomMode));\r
 \r
+  //\r
+  // Check "certdb" variable's existence.\r
+  // If it doesn't exist, then create a new one with \r
+  // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.\r
+  //\r
+  Status = FindVariable (\r
+             EFI_CERT_DB_NAME,\r
+             &gEfiCertDbGuid,\r
+             &Variable,\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
+             );\r
+\r
+  if (Variable.CurrPtr == NULL) {\r
+    VarAttr  = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
+    ListSize = 0;\r
+    Status   = UpdateVariable (\r
+                 EFI_CERT_DB_NAME,\r
+                 &gEfiCertDbGuid,\r
+                 &ListSize,\r
+                 sizeof (UINT32),\r
+                 VarAttr,\r
+                 0,\r
+                 0,\r
+                 &Variable,\r
+                 NULL\r
+                 );\r
+\r
+  }  \r
+\r
   return Status;\r
 }\r
 \r
@@ -887,7 +918,16 @@ ProcessVarWithPk (
       // Verify against X509 Cert PK.\r
       //\r
       Del    = FALSE;\r
-      Status = VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, TRUE, &Del);\r
+      Status = VerifyTimeBasedPayload (\r
+                 VariableName,\r
+                 VendorGuid,\r
+                 Data,\r
+                 DataSize,\r
+                 Variable,\r
+                 Attributes,\r
+                 AuthVarTypePk,\r
+                 &Del\r
+                 );\r
       if (!EFI_ERROR (Status)) {\r
         //\r
         // If delete PK in user mode, need change to setup mode.\r
@@ -1084,7 +1124,16 @@ ProcessVarWithKek (
       //\r
       // Time-based, verify against X509 Cert KEK.\r
       //\r
-      return VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, FALSE, NULL);\r
+      return VerifyTimeBasedPayload (\r
+               VariableName,\r
+               VendorGuid,\r
+               Data,\r
+               DataSize,\r
+               Variable,\r
+               Attributes,\r
+               AuthVarTypeKek,\r
+               NULL\r
+               );\r
     } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
       //\r
       // Counter-based, verify against RSA2048 Cert KEK.\r
@@ -1255,7 +1304,16 @@ ProcessVariable (
   // Process Time-based Authenticated variable.\r
   //\r
   if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
-    return VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, FALSE, NULL);\r
+    return VerifyTimeBasedPayload (\r
+             VariableName,\r
+             VendorGuid,\r
+             Data,\r
+             DataSize,\r
+             Variable,\r
+             Attributes,\r
+             AuthVarTypePriv,\r
+             NULL\r
+             );\r
   }\r
 \r
   //\r
@@ -1489,6 +1547,470 @@ CompareTimeStamp (
   return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);\r
 }\r
 \r
+/**\r
+  Find matching signer's certificates for common authenticated variable\r
+  by corresponding VariableName and VendorGuid from "certdb".\r
+\r
+  The data format of "certdb":\r
+  //\r
+  //     UINT32 CertDbListSize;\r
+  // /// AUTH_CERT_DB_DATA Certs1[];\r
+  // /// AUTH_CERT_DB_DATA Certs2[];\r
+  // /// ...\r
+  // /// AUTH_CERT_DB_DATA Certsn[];\r
+  //\r
+\r
+  @param[in]  VariableName   Name of authenticated Variable.\r
+  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.\r
+  @param[in]  Data           Pointer to variable "certdb".\r
+  @param[in]  DataSize       Size of variable "certdb".\r
+  @param[out] CertOffset     Offset of matching CertData, from starting of Data.\r
+  @param[out] CertDataSize   Length of CertData in bytes.\r
+  @param[out] CertNodeOffset Offset of matching AUTH_CERT_DB_DATA , from\r
+                             starting of Data.\r
+  @param[out] CertNodeSize   Length of AUTH_CERT_DB_DATA in bytes.\r
+\r
+  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+  @retval  EFI_NOT_FOUND         Fail to find matching certs.\r
+  @retval  EFI_SUCCESS           Find matching certs and output parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+FindCertsFromDb (\r
+  IN     CHAR16           *VariableName,\r
+  IN     EFI_GUID         *VendorGuid,\r
+  IN     UINT8            *Data,\r
+  IN     UINTN            DataSize,\r
+  OUT    UINT32           *CertOffset,    OPTIONAL\r
+  OUT    UINT32           *CertDataSize,  OPTIONAL\r
+  OUT    UINT32           *CertNodeOffset,OPTIONAL\r
+  OUT    UINT32           *CertNodeSize   OPTIONAL\r
+  )\r
+{\r
+  UINT32                  Offset;\r
+  AUTH_CERT_DB_DATA       *Ptr;\r
+  UINT32                  CertSize;\r
+  UINT32                  NameSize;\r
+  UINT32                  NodeSize;\r
+  UINT32                  CertDbListSize;\r
+\r
+  if ((VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Check whether DataSize matches recorded CertDbListSize.\r
+  //\r
+  if (DataSize < sizeof (UINT32)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  CertDbListSize = ReadUnaligned32 ((UINT32 *) Data);\r
+\r
+  if (CertDbListSize != (UINT32) DataSize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Offset = sizeof (UINT32);\r
+\r
+  //\r
+  // Get corresponding certificates by VendorGuid and VariableName.\r
+  //\r
+  while (Offset < (UINT32) DataSize) {\r
+    Ptr = (AUTH_CERT_DB_DATA *) (Data + Offset);\r
+    //\r
+    // Check whether VendorGuid matches.\r
+    //\r
+    if (CompareGuid (&Ptr->VendorGuid, VendorGuid)) {\r
+      NodeSize = ReadUnaligned32 (&Ptr->CertNodeSize);\r
+      NameSize = ReadUnaligned32 (&Ptr->NameSize);\r
+      CertSize = ReadUnaligned32 (&Ptr->CertDataSize);\r
+\r
+      if (NodeSize != sizeof (EFI_GUID) + sizeof (UINT32) * 3 + CertSize +\r
+          sizeof (CHAR16) * NameSize) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+      Offset = Offset + sizeof (EFI_GUID) + sizeof (UINT32) * 3;\r
+      //\r
+      // Check whether VariableName matches.\r
+      //\r
+      if ((NameSize == StrLen (VariableName)) && \r
+          (CompareMem (Data + Offset, VariableName, NameSize * sizeof (CHAR16)) == 0)) {\r
+        Offset = Offset + NameSize * sizeof (CHAR16);\r
+\r
+        if (CertOffset != NULL) {\r
+          *CertOffset = Offset;\r
+        }\r
+\r
+        if (CertDataSize != NULL) {\r
+          *CertDataSize = CertSize;        \r
+        }\r
+\r
+        if (CertNodeOffset != NULL) {\r
+          *CertNodeOffset = (UINT32) ((UINT8 *) Ptr - Data);\r
+        }\r
+\r
+        if (CertNodeSize != NULL) {\r
+          *CertNodeSize = NodeSize;\r
+        }\r
+\r
+        return EFI_SUCCESS;\r
+      } else {\r
+        Offset = Offset + NameSize * sizeof (CHAR16) + CertSize;\r
+      }\r
+    } else {\r
+      NodeSize = ReadUnaligned32 (&Ptr->CertNodeSize);\r
+      Offset   = Offset + NodeSize;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;  \r
+}\r
+\r
+/**\r
+  Retrieve signer's certificates for common authenticated variable\r
+  by corresponding VariableName and VendorGuid from "certdb".\r
+\r
+  @param[in]  VariableName   Name of authenticated Variable.\r
+  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.\r
+  @param[out] CertData       Pointer to signer's certificates.\r
+  @param[out] CertDataSize   Length of CertData in bytes.\r
+\r
+  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+  @retval  EFI_NOT_FOUND         Fail to find "certdb" or matching certs.\r
+  @retval  EFI_SUCCESS           Get signer's certificates successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetCertsFromDb (\r
+  IN     CHAR16           *VariableName,\r
+  IN     EFI_GUID         *VendorGuid,\r
+  OUT    UINT8            **CertData,\r
+  OUT    UINT32           *CertDataSize\r
+  )\r
+{\r
+  VARIABLE_POINTER_TRACK  CertDbVariable;\r
+  EFI_STATUS              Status;\r
+  UINT8                   *Data;\r
+  UINTN                   DataSize;\r
+  UINT32                  CertOffset;\r
+\r
+  if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL) || (CertDataSize == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // Get variable "certdb".\r
+  //\r
+  Status = FindVariable (\r
+             EFI_CERT_DB_NAME,\r
+             &gEfiCertDbGuid,\r
+             &CertDbVariable,\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
+             );      \r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DataSize  = DataSizeOfVariable (CertDbVariable.CurrPtr);\r
+  Data      = GetVariableDataPtr (CertDbVariable.CurrPtr);\r
+  if ((DataSize == 0) || (Data == NULL)) {\r
+    ASSERT (FALSE);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Status = FindCertsFromDb (\r
+             VariableName,\r
+             VendorGuid,\r
+             Data,\r
+             DataSize,\r
+             &CertOffset,\r
+             CertDataSize,\r
+             NULL,\r
+             NULL\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  *CertData = Data + CertOffset;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Delete matching signer's certificates when deleting common authenticated\r
+  variable by corresponding VariableName and VendorGuid from "certdb".\r
+\r
+  @param[in]  VariableName   Name of authenticated Variable.\r
+  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.\r
+\r
+  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+  @retval  EFI_NOT_FOUND         Fail to find "certdb" or matching certs.\r
+  @retval  EFI_OUT_OF_RESOURCES  The operation is failed due to lack of resources.\r
+  @retval  EFI_SUCCESS           The operation is completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteCertsFromDb (\r
+  IN     CHAR16           *VariableName,\r
+  IN     EFI_GUID         *VendorGuid\r
+  )\r
+{\r
+  VARIABLE_POINTER_TRACK  CertDbVariable;\r
+  EFI_STATUS              Status;\r
+  UINT8                   *Data;\r
+  UINTN                   DataSize;\r
+  UINT32                  VarAttr;\r
+  UINT32                  CertNodeOffset;\r
+  UINT32                  CertNodeSize;\r
+  UINT8                   *NewCertDb;\r
+  UINT32                  NewCertDbSize;\r
+\r
+  if ((VariableName == NULL) || (VendorGuid == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // Get variable "certdb".\r
+  //\r
+  Status = FindVariable (\r
+             EFI_CERT_DB_NAME,\r
+             &gEfiCertDbGuid,\r
+             &CertDbVariable,\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
+             );      \r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DataSize  = DataSizeOfVariable (CertDbVariable.CurrPtr);\r
+  Data      = GetVariableDataPtr (CertDbVariable.CurrPtr);\r
+  if ((DataSize == 0) || (Data == NULL)) {\r
+    ASSERT (FALSE);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (DataSize == sizeof (UINT32)) {\r
+    //\r
+    // There is no certs in certdb.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get corresponding cert node from certdb.\r
+  //\r
+  Status = FindCertsFromDb (\r
+             VariableName,\r
+             VendorGuid,\r
+             Data,\r
+             DataSize,\r
+             NULL,\r
+             NULL,\r
+             &CertNodeOffset,\r
+             &CertNodeSize\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (DataSize < (CertNodeOffset + CertNodeSize)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Construct new data content of variable "certdb".\r
+  //\r
+  NewCertDbSize = (UINT32) DataSize - CertNodeSize;\r
+  NewCertDb     = AllocateZeroPool (NewCertDbSize);\r
+  if (NewCertDb == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Copy the DB entries before deleting node.\r
+  //\r
+  CopyMem (NewCertDb, Data, CertNodeOffset);\r
+  //\r
+  // Update CertDbListSize.\r
+  //\r
+  CopyMem (NewCertDb, &NewCertDbSize, sizeof (UINT32));\r
+  //\r
+  // Copy the DB entries after deleting node.\r
+  //\r
+  if (DataSize > (CertNodeOffset + CertNodeSize)) {\r
+    CopyMem (\r
+      NewCertDb + CertNodeOffset,\r
+      Data + CertNodeOffset + CertNodeSize,\r
+      DataSize - CertNodeOffset - CertNodeSize\r
+      );\r
+  }\r
+\r
+  //\r
+  // Set "certdb".\r
+  // \r
+  VarAttr  = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;  \r
+  Status   = UpdateVariable (\r
+               EFI_CERT_DB_NAME,\r
+               &gEfiCertDbGuid,\r
+               NewCertDb,\r
+               NewCertDbSize,\r
+               VarAttr,\r
+               0,\r
+               0,\r
+               &CertDbVariable,\r
+               NULL\r
+               );\r
+\r
+  FreePool (NewCertDb);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Insert signer's certificates for common authenticated variable with VariableName\r
+  and VendorGuid in AUTH_CERT_DB_DATA to "certdb".\r
+\r
+  @param[in]  VariableName   Name of authenticated Variable.\r
+  @param[in]  VendorGuid     Vendor GUID of authenticated Variable.\r
+  @param[in]  CertData       Pointer to signer's certificates.\r
+  @param[in]  CertDataSize   Length of CertData in bytes.\r
+\r
+  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+  @retval  EFI_ACCESS_DENIED     An AUTH_CERT_DB_DATA entry with same VariableName\r
+                                 and VendorGuid already exists.\r
+  @retval  EFI_OUT_OF_RESOURCES  The operation is failed due to lack of resources.\r
+  @retval  EFI_SUCCESS           Insert an AUTH_CERT_DB_DATA entry to "certdb"\r
+\r
+**/\r
+EFI_STATUS\r
+InsertCertsToDb (\r
+  IN     CHAR16           *VariableName,\r
+  IN     EFI_GUID         *VendorGuid,\r
+  IN     UINT8            *CertData,\r
+  IN     UINTN            CertDataSize\r
+  )\r
+{\r
+  VARIABLE_POINTER_TRACK  CertDbVariable;\r
+  EFI_STATUS              Status;\r
+  UINT8                   *Data;\r
+  UINTN                   DataSize;\r
+  UINT32                  VarAttr;\r
+  UINT8                   *NewCertDb;\r
+  UINT32                  NewCertDbSize;\r
+  UINT32                  CertNodeSize;\r
+  UINT32                  NameSize;\r
+  AUTH_CERT_DB_DATA       *Ptr;\r
+\r
+  if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // Get variable "certdb".\r
+  //\r
+  Status = FindVariable (\r
+             EFI_CERT_DB_NAME,\r
+             &gEfiCertDbGuid,\r
+             &CertDbVariable,\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
+             );      \r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DataSize  = DataSizeOfVariable (CertDbVariable.CurrPtr);\r
+  Data      = GetVariableDataPtr (CertDbVariable.CurrPtr);\r
+  if ((DataSize == 0) || (Data == NULL)) {\r
+    ASSERT (FALSE);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Find whether matching cert node already exists in "certdb".\r
+  // If yes return error.\r
+  //\r
+  Status = FindCertsFromDb (\r
+             VariableName,\r
+             VendorGuid,\r
+             Data,\r
+             DataSize,\r
+             NULL,\r
+             NULL,\r
+             NULL,\r
+             NULL\r
+             );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    ASSERT (FALSE);\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  //\r
+  // Construct new data content of variable "certdb".\r
+  //\r
+  NameSize      = (UINT32) StrLen (VariableName);\r
+  CertNodeSize  = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + NameSize * sizeof (CHAR16); \r
+  NewCertDbSize = (UINT32) DataSize + CertNodeSize;                  \r
+  NewCertDb     = AllocateZeroPool (NewCertDbSize);\r
+  if (NewCertDb == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Copy the DB entries before deleting node.\r
+  //\r
+  CopyMem (NewCertDb, Data, DataSize);\r
+  //\r
+  // Update CertDbListSize.\r
+  //\r
+  CopyMem (NewCertDb, &NewCertDbSize, sizeof (UINT32));\r
+  //\r
+  // Construct new cert node.\r
+  //\r
+  Ptr = (AUTH_CERT_DB_DATA *) (NewCertDb + DataSize);\r
+  CopyGuid (&Ptr->VendorGuid, VendorGuid);\r
+  CopyMem (&Ptr->CertNodeSize, &CertNodeSize, sizeof (UINT32));\r
+  CopyMem (&Ptr->NameSize, &NameSize, sizeof (UINT32));\r
+  CopyMem (&Ptr->CertDataSize, &CertDataSize, sizeof (UINT32));\r
+  \r
+  CopyMem (\r
+    (UINT8 *) Ptr + sizeof (AUTH_CERT_DB_DATA),\r
+    VariableName,\r
+    NameSize * sizeof (CHAR16)\r
+    );\r
+\r
+  CopyMem (\r
+    (UINT8 *) Ptr +  sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16),\r
+    CertData,\r
+    CertDataSize\r
+    );\r
+  \r
+  //\r
+  // Set "certdb".\r
+  // \r
+  VarAttr  = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;  \r
+  Status   = UpdateVariable (\r
+               EFI_CERT_DB_NAME,\r
+               &gEfiCertDbGuid,\r
+               NewCertDb,\r
+               NewCertDbSize,\r
+               VarAttr,\r
+               0,\r
+               0,\r
+               &CertDbVariable,\r
+               NULL\r
+               );\r
+\r
+  FreePool (NewCertDb);\r
+  return Status;\r
+}\r
+\r
 /**\r
   Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set\r
 \r
@@ -1499,7 +2021,7 @@ CompareTimeStamp (
                                           data, this value contains the required size.\r
   @param[in]  Variable                    The variable information which is used to keep track of variable usage.\r
   @param[in]  Attributes                  Attribute value of the variable.\r
-  @param[in]  Pk                          Verify against PK or KEK database.\r
+  @param[in]  AuthVarType                 Verify against PK or KEK database or private database.\r
   @param[out] VarDel                      Delete the variable or not.\r
 \r
   @retval EFI_INVALID_PARAMETER           Invalid parameter.\r
@@ -1518,7 +2040,7 @@ VerifyTimeBasedPayload (
   IN     UINTN                              DataSize,\r
   IN     VARIABLE_POINTER_TRACK             *Variable,\r
   IN     UINT32                             Attributes,\r
-  IN     BOOLEAN                            Pk,\r
+  IN     AUTHVAR_TYPE                       AuthVarType,\r
   OUT    BOOLEAN                            *VarDel\r
   )\r
 {\r
@@ -1532,7 +2054,6 @@ VerifyTimeBasedPayload (
   UINT32                           Attr;\r
   UINT32                           SigDataSize;\r
   UINT32                           KekDataSize;\r
-  BOOLEAN                          Result;\r
   BOOLEAN                          VerifyStatus;\r
   EFI_STATUS                       Status;\r
   EFI_SIGNATURE_LIST               *CertList;\r
@@ -1544,12 +2065,19 @@ VerifyTimeBasedPayload (
   VARIABLE_POINTER_TRACK           PkVariable;\r
   UINT8                            *Buffer;\r
   UINTN                            Length;\r
+  UINT8                            *SignerCerts;\r
+  UINT8                            *WrapSigData;\r
+  UINTN                            CertStackSize;\r
+  UINT8                            *CertsInCertDb;\r
+  UINT32                           CertsSizeinDb;\r
 \r
-  Result                 = FALSE;\r
   VerifyStatus           = FALSE;\r
   CertData               = NULL;\r
   NewData                = NULL;\r
   Attr                   = Attributes;\r
+  WrapSigData            = NULL;\r
+  SignerCerts            = NULL;\r
+  RootCert               = NULL;\r
 \r
   //\r
   // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is\r
@@ -1633,7 +2161,7 @@ VerifyTimeBasedPayload (
 \r
   CopyMem (Buffer, PayloadPtr, PayloadSize);\r
 \r
-  if (Pk) {\r
+  if (AuthVarType == AuthVarTypePk) {\r
     //\r
     // Get platform key from variable.\r
     //\r
@@ -1666,7 +2194,7 @@ VerifyTimeBasedPayload (
                      NewDataSize\r
                      );\r
 \r
-  } else {\r
+  } else if (AuthVarType == AuthVarTypeKek) {\r
 \r
     //\r
     // Get KEK database from variable.\r
@@ -1718,10 +2246,85 @@ VerifyTimeBasedPayload (
       KekDataSize -= CertList->SignatureListSize;\r
       CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
     }\r
+  } else if (AuthVarType == AuthVarTypePriv) {\r
+\r
+    //\r
+    // Process common authenticated variable except PK/KEK/DB/DBX.\r
+    // Get signer's certificates from SignedData.\r
+    //\r
+    VerifyStatus = Pkcs7GetSigners (\r
+                     SigData,\r
+                     SigDataSize,\r
+                     &SignerCerts,\r
+                     &CertStackSize,\r
+                     &RootCert,\r
+                     &RootCertSize\r
+                     );\r
+    if (!VerifyStatus) {\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Get previously stored signer's certificates from certdb for existing\r
+    // variable. Check whether they are identical with signer's certificates\r
+    // in SignedData. If not, return error immediately.\r
+    //\r
+    if ((Variable->CurrPtr != NULL)) {\r
+      VerifyStatus = FALSE;\r
+\r
+      Status = GetCertsFromDb (VariableName, VendorGuid, &CertsInCertDb, &CertsSizeinDb);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      }\r
+    \r
+      if ((CertStackSize != CertsSizeinDb) ||\r
+          (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) {\r
+        goto Exit;\r
+      }\r
+    }\r
+\r
+    VerifyStatus = Pkcs7Verify (\r
+                     SigData,\r
+                     SigDataSize,\r
+                     RootCert,\r
+                     RootCertSize,\r
+                     NewData,\r
+                     NewDataSize\r
+                     );\r
+    if (!VerifyStatus) {\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Delete signer's certificates when delete the common authenticated variable.\r
+    //\r
+    if ((PayloadSize == 0) && (Variable->CurrPtr != NULL)) {\r
+      Status = DeleteCertsFromDb (VariableName, VendorGuid);\r
+      if (EFI_ERROR (Status)) {\r
+        VerifyStatus = FALSE;\r
+        goto Exit;\r
+      }\r
+    } else if (Variable->CurrPtr == NULL) {\r
+      //\r
+      // Insert signer's certificates when adding a new common authenticated variable.\r
+      //\r
+      Status = InsertCertsToDb (VariableName, VendorGuid, SignerCerts, CertStackSize);\r
+      if (EFI_ERROR (Status)) {\r
+        VerifyStatus = FALSE;\r
+        goto Exit;\r
+      }\r
+    }\r
+  } else {\r
+    return EFI_SECURITY_VIOLATION;\r
   }\r
 \r
 Exit:\r
 \r
+  if (AuthVarType == AuthVarTypePriv) {\r
+    Pkcs7FreeSigners (RootCert);\r
+    Pkcs7FreeSigners (SignerCerts);\r
+  }\r
+\r
   if (!VerifyStatus) {\r
     return EFI_SECURITY_VIOLATION;\r
   }\r
@@ -1738,15 +2341,16 @@ Exit:
   //\r
   // Final step: Update/Append Variable if it pass Pkcs7Verify\r
   //\r
-  return   UpdateVariable (\r
-             VariableName,\r
-             VendorGuid,\r
-             PayloadPtr,\r
-             PayloadSize,\r
-             Attributes,\r
-             0,\r
-             0,\r
-             Variable,\r
-             &CertData->TimeStamp\r
-             );\r
+  return UpdateVariable (\r
+           VariableName,\r
+           VendorGuid,\r
+           PayloadPtr,\r
+           PayloadSize,\r
+           Attributes,\r
+           0,\r
+           0,\r
+           Variable,\r
+           &CertData->TimeStamp\r
+           );\r
 }\r
+\r
index 9a022f38f9e8e4a82fc926010e5c09e36674ea90..4419c9174436721f7bd77f576e9b62512018aaa4 100644 (file)
@@ -2,7 +2,7 @@
   The internal header file includes the common header files, defines\r
   internal structure and functions used by AuthService module.\r
 \r
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
 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
@@ -56,6 +56,23 @@ typedef struct {
   UINT32      SigDataSize;\r
 } EFI_SIGNATURE_ITEM;\r
 \r
+typedef enum {\r
+  AuthVarTypePk,\r
+  AuthVarTypeKek,\r
+  AuthVarTypePriv\r
+} AUTHVAR_TYPE;\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+  EFI_GUID    VendorGuid;\r
+  UINT32      CertNodeSize;\r
+  UINT32      NameSize;\r
+  UINT32      CertDataSize;\r
+  /// CHAR16  VariableName[NameSize];\r
+  /// UINT8   CertData[CertDataSize];\r
+} AUTH_CERT_DB_DATA;\r
+#pragma pack()\r
+\r
 /**\r
   Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.\r
 \r
@@ -247,7 +264,7 @@ CompareTimeStamp (
                                           data, this value contains the required size.\r
   @param[in]  Variable                    The variable information which is used to keep track of variable usage.\r
   @param[in]  Attributes                  Attribute value of the variable.\r
-  @param[in]  Pk                          Verify against PK or KEK database.\r
+  @param[in]  AuthVarType                 Verify against PK or KEK database or private database.\r
   @param[out] VarDel                      Delete the variable or not.\r
 \r
   @retval EFI_INVALID_PARAMETER           Invalid parameter.\r
@@ -266,7 +283,7 @@ VerifyTimeBasedPayload (
   IN     UINTN                              DataSize,\r
   IN     VARIABLE_POINTER_TRACK             *Variable,\r
   IN     UINT32                             Attributes,\r
-  IN     BOOLEAN                            Pk,\r
+  IN     AUTHVAR_TYPE                       AuthVarType,\r
   OUT    BOOLEAN                            *VarDel\r
   );\r
 \r
index abe14abab30dbd791fdffe984f2c5d61d8947a5b..7b151863539b0c9faf595f0202af782beefdfce8 100644 (file)
@@ -75,6 +75,7 @@
   gEfiSecureBootEnableDisableGuid\r
   gEfiCustomModeEnableGuid\r
   gEfiSystemNvDataFvGuid                        ## CONSUMES\r
+  gEfiCertDbGuid\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize\r
index cd6457f8f488963c93b4feabfec88c8759ec503b..a62fd43989b2666bb1a8c1150bd7e427ef6ae408 100644 (file)
@@ -80,6 +80,7 @@
   gEfiSecureBootEnableDisableGuid\r
   gEfiCustomModeEnableGuid\r
   gEfiSystemNvDataFvGuid                        ## CONSUMES\r
+  gEfiCertDbGuid\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize\r