]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
Add PubKey index check before touching PubKey cache. Internal PubKey Variable PubkeyI...
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / RuntimeDxe / AuthService.c
index ee45ec97767de0e9b45b730f5e6cec97068170e1..49d7648f66557f11a1071791529b1fc5be201100 100644 (file)
@@ -15,7 +15,7 @@
   They will do basic validation for authentication data structure, then call crypto library\r
   to verify the signature.\r
 \r
-Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2014, 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
@@ -32,9 +32,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 ///\r
 /// Global database array for scratch\r
 ///\r
-UINT8    mPubKeyStore[MAX_KEYDB_SIZE];\r
+UINT8    *mPubKeyStore;\r
 UINT32   mPubKeyNumber;\r
-UINT8    mCertDbStore[MAX_CERTDB_SIZE];\r
+UINT32   mMaxKeyNumber;\r
+UINT32   mMaxKeyDbSize;\r
+UINT8    *mCertDbStore;\r
+UINT32   mMaxCertDbSize;\r
 UINT32   mPlatformMode;\r
 UINT8    mVendorKeyState;\r
 \r
@@ -183,6 +186,25 @@ AutenticatedVariableServiceInitialize (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  //\r
+  // Reserve runtime buffer for public key database. The size excludes variable header and name size.\r
+  //\r
+  mMaxKeyDbSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - sizeof (AUTHVAR_KEYDB_NAME);\r
+  mMaxKeyNumber = mMaxKeyDbSize / EFI_CERT_TYPE_RSA2048_SIZE;\r
+  mPubKeyStore  = AllocateRuntimePool (mMaxKeyDbSize);\r
+  if (mPubKeyStore == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Reserve runtime buffer for certificate database. The size excludes variable header and name size.\r
+  //\r
+  mMaxCertDbSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - sizeof (EFI_CERT_DB_NAME);\r
+  mCertDbStore   = AllocateRuntimePool (mMaxCertDbSize);\r
+  if (mCertDbStore == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
   //\r
   // Prepare runtime buffer for serialized data of time-based authenticated\r
   // Variable, i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data).\r
@@ -450,22 +472,26 @@ AutenticatedVariableServiceInitialize (
   Add public key in store and return its index.\r
 \r
   @param[in]  PubKey                  Input pointer to Public Key data\r
+  @param[in]  VariableDataEntry       The variable data entry \r
 \r
   @return                             Index of new added item\r
 \r
 **/\r
 UINT32\r
 AddPubKeyInStore (\r
-  IN  UINT8               *PubKey\r
+  IN  UINT8                        *PubKey,\r
+  IN  VARIABLE_ENTRY_CONSISTENCY   *VariableDataEntry\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
-  BOOLEAN                 IsFound;\r
-  UINT32                  Index;\r
-  VARIABLE_POINTER_TRACK  Variable;\r
-  UINT8                   *Ptr;\r
-  UINT8                   *Data;\r
-  UINTN                   DataSize;\r
+  EFI_STATUS                       Status;\r
+  BOOLEAN                          IsFound;\r
+  UINT32                           Index;\r
+  VARIABLE_POINTER_TRACK           Variable;\r
+  UINT8                            *Ptr;\r
+  UINT8                            *Data;\r
+  UINTN                            DataSize;\r
+  VARIABLE_ENTRY_CONSISTENCY       PublicKeyEntry;\r
+  UINT32                           Attributes;\r
 \r
   if (PubKey == NULL) {\r
     return 0;\r
@@ -478,8 +504,8 @@ AddPubKeyInStore (
              &mVariableModuleGlobal->VariableGlobal,\r
              FALSE\r
              );\r
-  ASSERT_EFI_ERROR (Status);\r
   if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Get public key database variable failure, Status = %r\n", Status));\r
     return 0;\r
   }\r
 \r
@@ -499,7 +525,7 @@ AddPubKeyInStore (
     //\r
     // Add public key in database.\r
     //\r
-    if (mPubKeyNumber == MAX_KEY_NUM) {\r
+    if (mPubKeyNumber == mMaxKeyNumber) {\r
       //\r
       // Public key dadatase is full, try to reclaim invalid key.\r
       //\r
@@ -530,8 +556,8 @@ AddPubKeyInStore (
                  &mVariableModuleGlobal->VariableGlobal,\r
                  FALSE\r
                  );\r
-      ASSERT_EFI_ERROR (Status);\r
       if (EFI_ERROR (Status)) {\r
+        DEBUG ((EFI_D_ERROR, "Get public key database variable failure, Status = %r\n", Status));\r
         return 0;\r
       }\r
 \r
@@ -541,11 +567,26 @@ AddPubKeyInStore (
       CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);\r
       mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);\r
 \r
-      if (mPubKeyNumber == MAX_KEY_NUM) {\r
+      if (mPubKeyNumber == mMaxKeyNumber) {\r
         return 0;\r
       }     \r
     }\r
 \r
+    //\r
+    // Check the variable space for both public key and variable data.\r
+    //\r
+    PublicKeyEntry.VariableSize = (mPubKeyNumber + 1) * EFI_CERT_TYPE_RSA2048_SIZE;\r
+    PublicKeyEntry.Guid         = &gEfiAuthenticatedVariableGuid;\r
+    PublicKeyEntry.Name         = AUTHVAR_KEYDB_NAME;\r
+    Attributes = VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;\r
+\r
+    if (!CheckRemainingSpaceForConsistency (Attributes, &PublicKeyEntry, VariableDataEntry, NULL)) {\r
+      //\r
+      // No enough variable space.\r
+      //\r
+      return 0;\r
+    }\r
+\r
     CopyMem (mPubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
     Index = ++mPubKeyNumber;\r
     //\r
@@ -556,13 +597,16 @@ AddPubKeyInStore (
                &gEfiAuthenticatedVariableGuid,\r
                mPubKeyStore,\r
                mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE,\r
-               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,\r
+               Attributes,\r
                0,\r
                0,\r
                &Variable,\r
                NULL\r
                );\r
-    ASSERT_EFI_ERROR (Status);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Update public key database variable failure, Status = %r\n", Status));\r
+      return 0;\r
+    }\r
   }\r
 \r
   return Index;\r
@@ -1268,6 +1312,7 @@ ProcessVariable (
   EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlock;\r
   UINT32                          KeyIndex;\r
   UINT64                          MonotonicCount;\r
+  VARIABLE_ENTRY_CONSISTENCY      VariableDataEntry;\r
 \r
   KeyIndex    = 0;\r
   CertData    = NULL;\r
@@ -1365,9 +1410,11 @@ ProcessVariable (
 \r
   if (!IsFirstTime) {\r
     //\r
-    // Check input PubKey.\r
+    // 2 cases need to check here\r
+    //   1. Internal PubKey variable. PubKeyIndex is always 0 \r
+    //   2. Other counter-based AuthVariable. Check input PubKey.\r
     //\r
-    if (CompareMem (PubKey, mPubKeyStore + (KeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE, EFI_CERT_TYPE_RSA2048_SIZE) != 0) {\r
+    if (KeyIndex == 0 || CompareMem (PubKey, mPubKeyStore + (KeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE, EFI_CERT_TYPE_RSA2048_SIZE) != 0) {\r
       return EFI_SECURITY_VIOLATION;\r
     }\r
     //\r
@@ -1393,10 +1440,14 @@ ProcessVariable (
   // Now, the signature has been verified!\r
   //\r
   if (IsFirstTime && !IsDeletion) {\r
+    VariableDataEntry.VariableSize = DataSize - AUTHINFO_SIZE;\r
+    VariableDataEntry.Guid         = VendorGuid;\r
+    VariableDataEntry.Name         = VariableName;\r
+\r
     //\r
     // Update public key database variable if need.\r
     //\r
-    KeyIndex = AddPubKeyInStore (PubKey);\r
+    KeyIndex = AddPubKeyInStore (PubKey, &VariableDataEntry);\r
     if (KeyIndex == 0) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
@@ -1969,7 +2020,7 @@ InsertCertsToDb (
   NameSize      = (UINT32) StrLen (VariableName);\r
   CertNodeSize  = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + NameSize * sizeof (CHAR16); \r
   NewCertDbSize = (UINT32) DataSize + CertNodeSize;\r
-  if (NewCertDbSize > MAX_CERTDB_SIZE) {\r
+  if (NewCertDbSize > mMaxCertDbSize) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   NewCertDb     = (UINT8*) mCertDbStore;\r
@@ -2095,6 +2146,7 @@ VerifyTimeBasedPayload (
   WrapSigData            = NULL;\r
   SignerCerts            = NULL;\r
   RootCert               = NULL;\r
+  CertsInCertDb          = NULL;\r
 \r
   //\r
   // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is\r