//\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
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
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
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
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
///\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
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