]> git.proxmox.com Git - mirror_edk2.git/commitdiff
1. Check input PK/KEK variable data to make sure it is a valid EFI_SIGNATURE_LIST.
authorsfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 23 Nov 2011 05:10:40 +0000 (05:10 +0000)
committersfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 23 Nov 2011 05:10:40 +0000 (05:10 +0000)
Signed-off-by: sfu5
Reviewed-by: gdong1
Reviewed-by : czhan46

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12765 6f19259b-4bc3-4df7-8a09-765794883524

SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.h

index 5287c20cba067d728901735e52f8bb0f2371ff64..3aa6de0fd26d8167d0cfc4ec1a76a371d950821a 100644 (file)
@@ -48,6 +48,23 @@ VOID  *mStorageArea = NULL;
 //\r
 UINT8 *mSerializationRuntimeBuffer = NULL;\r
 \r
+//\r
+// Requirement for different signature type which have been defined in UEFI spec.\r
+// These data are used to peform SignatureList format check while setting PK/KEK variable.\r
+//\r
+EFI_SIGNATURE_ITEM mSupportSigItem[] = {\r
+//{SigType,                       SigHeaderSize,   SigDataSize  }\r
+  {EFI_CERT_SHA256_GUID,          0,               32           },\r
+  {EFI_CERT_RSA2048_GUID,         0,               256          },\r
+  {EFI_CERT_RSA2048_SHA256_GUID,  0,               256          },\r
+  {EFI_CERT_SHA1_GUID,            0,               20           },\r
+  {EFI_CERT_RSA2048_SHA1_GUID,    0,               256          },\r
+  {EFI_CERT_X509_GUID,            0,               ((UINT32) ~0)},\r
+  {EFI_CERT_SHA224_GUID,          0,               28           },\r
+  {EFI_CERT_SHA384_GUID,          0,               48           },\r
+  {EFI_CERT_SHA512_GUID,          0,               64           }\r
+};\r
+\r
 /**\r
   Internal function to delete a Variable given its name and GUID, no authentication\r
   required.\r
@@ -652,6 +669,100 @@ UpdatePlatformMode (
   return Status;\r
 }\r
 \r
+/**\r
+  Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK variable.\r
+\r
+  @param[in]  VariableName                Name of Variable to be check.\r
+  @param[in]  VendorGuid                  Variable vendor GUID.\r
+  @param[in]  Data                        Point to the variable data to be checked.\r
+  @param[in]  DataSize                    Size of Data.\r
+\r
+  @return EFI_INVALID_PARAMETER           Invalid signature list format.\r
+  @return EFI_SUCCESS                     Passed signature list format check successfully.\r
+  \r
+**/\r
+EFI_STATUS\r
+CheckSignatureListFormat(\r
+  IN  CHAR16                    *VariableName,\r
+  IN  EFI_GUID                  *VendorGuid,\r
+  IN  VOID                      *Data,\r
+  IN  UINTN                     DataSize\r
+  )\r
+{\r
+  EFI_SIGNATURE_LIST     *SigList;\r
+  UINTN                  SigDataSize;\r
+  UINT32                 Index;\r
+  UINT32                 SigCount;\r
+  BOOLEAN                IsPk;\r
+\r
+  if (DataSize == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  ASSERT (VariableName != NULL && VendorGuid != NULL && Data != NULL);\r
+\r
+  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0)){\r
+    IsPk = TRUE;\r
+  } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {\r
+    IsPk = FALSE;\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  SigCount = 0;\r
+  SigList  = (EFI_SIGNATURE_LIST *) Data;\r
+  SigDataSize  = DataSize;\r
+\r
+  //\r
+  // Walk throuth the input signature list and check the data format.\r
+  // If any signature is incorrectly formed, the whole check will fail.\r
+  //\r
+  while ((SigDataSize > 0) && (SigDataSize >= SigList->SignatureListSize)) {\r
+    for (Index = 0; Index < (sizeof (mSupportSigItem) / sizeof (EFI_SIGNATURE_ITEM)); Index++ ) {\r
+      if (CompareGuid (&SigList->SignatureType, &mSupportSigItem[Index].SigType)) {\r
+        //\r
+        // The value of SignatureSize should always be 16 (size of SignatureOwner \r
+        // component) add the data length according to signature type.\r
+        //\r
+        if (mSupportSigItem[Index].SigDataSize != ((UINT32) ~0) && \r
+          (SigList->SignatureSize - sizeof (EFI_GUID)) != mSupportSigItem[Index].SigDataSize) {\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+        if (mSupportSigItem[Index].SigHeaderSize != ((UINTN) ~0) &&\r
+          SigList->SignatureHeaderSize != mSupportSigItem[Index].SigHeaderSize) {\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Index == (sizeof (mSupportSigItem) / sizeof (EFI_SIGNATURE_ITEM))) {\r
+      //\r
+      // Undefined signature type.\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if ((SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) % SigList->SignatureSize != 0) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    SigCount += (SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) / SigList->SignatureSize;\r
+    \r
+    SigDataSize -= SigList->SignatureListSize;\r
+    SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);\r
+  }\r
+\r
+  if (((UINTN) SigList - (UINTN) Data) != DataSize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (IsPk && SigCount > 1) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Process variable with platform key for verification.\r
 \r
@@ -757,6 +868,15 @@ ProcessVarWithPk (
       OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize);\r
       Status    = VerifyCounterBasedPayload (Data, DataSize, OldPkData->SignatureData);\r
       if (!EFI_ERROR (Status)) {\r
+        Status = CheckSignatureListFormat(\r
+                   VariableName,\r
+                   VendorGuid,\r
+                   (UINT8*)Data + AUTHINFO_SIZE,\r
+                   DataSize - AUTHINFO_SIZE);\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+        \r
         Status = UpdateVariable (\r
                    VariableName,\r
                    VendorGuid,\r
@@ -809,6 +929,11 @@ ProcessVarWithPk (
       PayloadSize = DataSize;\r
     }\r
 \r
+    Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
     Status = UpdateVariable (\r
                VariableName,\r
                VendorGuid,\r
@@ -1496,6 +1621,11 @@ Exit:
     return EFI_SECURITY_VIOLATION;\r
   }\r
 \r
+  Status = CheckSignatureListFormat(VariableName, VendorGuid, PayloadPtr, PayloadSize);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   if ((PayloadSize == 0) && (VarDel != NULL)) {\r
     *VarDel = TRUE;\r
   }\r
index 54e2ac0a435b7912b1a5c8645874995bbe860dab..36ec9c10cd210996f3a59f63f75708227fff1c74 100644 (file)
@@ -49,6 +49,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 ///\r
 #define SIGSUPPORT_NUM 2\r
 \r
+///\r
+/// Struct to record signature requirement defined by UEFI spec.\r
+/// For SigHeaderSize and SigDataSize, ((UINT32) ~0) means NO exact length requirement for this field.\r
+///\r
+typedef struct {\r
+  EFI_GUID    SigType;\r
+  // Expected SignatureHeader size in Bytes.\r
+  UINT32      SigHeaderSize;\r
+  // Expected SignatureData size in Bytes.\r
+  UINT32      SigDataSize;\r
+} EFI_SIGNATURE_ITEM;\r
 \r
 /**\r
   Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.\r
@@ -116,6 +127,26 @@ CryptLibraryInitialize (
   VOID\r
   );\r
 \r
+/**\r
+  Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK variable.\r
+\r
+  @param[in]  VariableName                Name of Variable to be check.\r
+  @param[in]  VendorGuid                  Variable vendor GUID.\r
+  @param[in]  Data                        Point to the variable data to be checked.\r
+  @param[in]  DataSize                    Size of Data.\r
+\r
+  @return EFI_INVALID_PARAMETER           Invalid signature list format.\r
+  @return EFI_SUCCESS                     Passed signature list format check successfully.\r
+  \r
+**/\r
+EFI_STATUS\r
+CheckSignatureListFormat(\r
+  IN  CHAR16                    *VariableName,\r
+  IN  EFI_GUID                  *VendorGuid,\r
+  IN  VOID                      *Data,\r
+  IN  UINTN                     DataSize\r
+  );\r
+\r
 /**\r
   Process variable with platform key for verification.\r
 \r