1. Check input PK/KEK variable data to make sure it is a valid EFI_SIGNATURE_LIST.

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
This commit is contained in:
sfu5 2011-11-23 05:10:40 +00:00
parent e1982d4ca9
commit d912bad783
2 changed files with 161 additions and 0 deletions

View File

@ -48,6 +48,23 @@ VOID *mStorageArea = NULL;
//
UINT8 *mSerializationRuntimeBuffer = NULL;
//
// Requirement for different signature type which have been defined in UEFI spec.
// These data are used to peform SignatureList format check while setting PK/KEK variable.
//
EFI_SIGNATURE_ITEM mSupportSigItem[] = {
//{SigType, SigHeaderSize, SigDataSize }
{EFI_CERT_SHA256_GUID, 0, 32 },
{EFI_CERT_RSA2048_GUID, 0, 256 },
{EFI_CERT_RSA2048_SHA256_GUID, 0, 256 },
{EFI_CERT_SHA1_GUID, 0, 20 },
{EFI_CERT_RSA2048_SHA1_GUID, 0, 256 },
{EFI_CERT_X509_GUID, 0, ((UINT32) ~0)},
{EFI_CERT_SHA224_GUID, 0, 28 },
{EFI_CERT_SHA384_GUID, 0, 48 },
{EFI_CERT_SHA512_GUID, 0, 64 }
};
/**
Internal function to delete a Variable given its name and GUID, no authentication
required.
@ -652,6 +669,100 @@ UpdatePlatformMode (
return Status;
}
/**
Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK variable.
@param[in] VariableName Name of Variable to be check.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Data Point to the variable data to be checked.
@param[in] DataSize Size of Data.
@return EFI_INVALID_PARAMETER Invalid signature list format.
@return EFI_SUCCESS Passed signature list format check successfully.
**/
EFI_STATUS
CheckSignatureListFormat(
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN VOID *Data,
IN UINTN DataSize
)
{
EFI_SIGNATURE_LIST *SigList;
UINTN SigDataSize;
UINT32 Index;
UINT32 SigCount;
BOOLEAN IsPk;
if (DataSize == 0) {
return EFI_SUCCESS;
}
ASSERT (VariableName != NULL && VendorGuid != NULL && Data != NULL);
if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0)){
IsPk = TRUE;
} else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {
IsPk = FALSE;
} else {
return EFI_SUCCESS;
}
SigCount = 0;
SigList = (EFI_SIGNATURE_LIST *) Data;
SigDataSize = DataSize;
//
// Walk throuth the input signature list and check the data format.
// If any signature is incorrectly formed, the whole check will fail.
//
while ((SigDataSize > 0) && (SigDataSize >= SigList->SignatureListSize)) {
for (Index = 0; Index < (sizeof (mSupportSigItem) / sizeof (EFI_SIGNATURE_ITEM)); Index++ ) {
if (CompareGuid (&SigList->SignatureType, &mSupportSigItem[Index].SigType)) {
//
// The value of SignatureSize should always be 16 (size of SignatureOwner
// component) add the data length according to signature type.
//
if (mSupportSigItem[Index].SigDataSize != ((UINT32) ~0) &&
(SigList->SignatureSize - sizeof (EFI_GUID)) != mSupportSigItem[Index].SigDataSize) {
return EFI_INVALID_PARAMETER;
}
if (mSupportSigItem[Index].SigHeaderSize != ((UINTN) ~0) &&
SigList->SignatureHeaderSize != mSupportSigItem[Index].SigHeaderSize) {
return EFI_INVALID_PARAMETER;
}
break;
}
}
if (Index == (sizeof (mSupportSigItem) / sizeof (EFI_SIGNATURE_ITEM))) {
//
// Undefined signature type.
//
return EFI_INVALID_PARAMETER;
}
if ((SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) % SigList->SignatureSize != 0) {
return EFI_INVALID_PARAMETER;
}
SigCount += (SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) / SigList->SignatureSize;
SigDataSize -= SigList->SignatureListSize;
SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);
}
if (((UINTN) SigList - (UINTN) Data) != DataSize) {
return EFI_INVALID_PARAMETER;
}
if (IsPk && SigCount > 1) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
/**
Process variable with platform key for verification.
@ -757,6 +868,15 @@ ProcessVarWithPk (
OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize);
Status = VerifyCounterBasedPayload (Data, DataSize, OldPkData->SignatureData);
if (!EFI_ERROR (Status)) {
Status = CheckSignatureListFormat(
VariableName,
VendorGuid,
(UINT8*)Data + AUTHINFO_SIZE,
DataSize - AUTHINFO_SIZE);
if (EFI_ERROR (Status)) {
return Status;
}
Status = UpdateVariable (
VariableName,
VendorGuid,
@ -809,6 +929,11 @@ ProcessVarWithPk (
PayloadSize = DataSize;
}
Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);
if (EFI_ERROR (Status)) {
return Status;
}
Status = UpdateVariable (
VariableName,
VendorGuid,
@ -1496,6 +1621,11 @@ Exit:
return EFI_SECURITY_VIOLATION;
}
Status = CheckSignatureListFormat(VariableName, VendorGuid, PayloadPtr, PayloadSize);
if (EFI_ERROR (Status)) {
return Status;
}
if ((PayloadSize == 0) && (VarDel != NULL)) {
*VarDel = TRUE;
}

View File

@ -49,6 +49,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
///
#define SIGSUPPORT_NUM 2
///
/// Struct to record signature requirement defined by UEFI spec.
/// For SigHeaderSize and SigDataSize, ((UINT32) ~0) means NO exact length requirement for this field.
///
typedef struct {
EFI_GUID SigType;
// Expected SignatureHeader size in Bytes.
UINT32 SigHeaderSize;
// Expected SignatureData size in Bytes.
UINT32 SigDataSize;
} EFI_SIGNATURE_ITEM;
/**
Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
@ -116,6 +127,26 @@ CryptLibraryInitialize (
VOID
);
/**
Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK variable.
@param[in] VariableName Name of Variable to be check.
@param[in] VendorGuid Variable vendor GUID.
@param[in] Data Point to the variable data to be checked.
@param[in] DataSize Size of Data.
@return EFI_INVALID_PARAMETER Invalid signature list format.
@return EFI_SUCCESS Passed signature list format check successfully.
**/
EFI_STATUS
CheckSignatureListFormat(
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN VOID *Data,
IN UINTN DataSize
);
/**
Process variable with platform key for verification.