SecurityPkg: Update VariableAuthenticated driver with following changes:

1. Remove memory allocation code in runtime.
2. Exclude NULL terminator in VariableName for serialization data in time-based variable authentication.
3. Add support for enroll PK with WRITE_ACCESS attribute.
4. Initialize SetupMode variable with correct NV attribute.
5. Add support for APPEND_WRITE attribute for non-existing Variable.
6. Clear KEK, DB and DBX as well as PK when user request to clear platform keys.
7. Check duplicated EFI_SIGNATURE_DATA for Variable formatted as EFI_SIGNATURE_LIST when APPEND_WRITE attribute is set.
8. Not change SecureBoot Variable in runtime, only update it in boot time since this Variable indicates firmware operating mode.
9. Save time stamp of PK when PK is set with TIME_BASED_WRITE_ACCESS attribute in setup mode.
10. Update to use PcdMaxVariableSize instead of PcdMaxAppendVariableSize for append operation.

Signed-off-by: xdu2
Reviewed-by: tye

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12599 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
xdu2 2011-10-28 09:55:09 +00:00
parent 45bf2c4789
commit 2d3fb91987
7 changed files with 706 additions and 429 deletions

View File

@ -323,7 +323,7 @@ CompareWithValidVariable (
/**
Return the variable store header and the index table based on the Index.
@param Index The index of the variable store.
@param Type The type of the variable store.
@param IndexTable Return the index table.
@return Pointer to the variable store header.

View File

@ -32,7 +32,6 @@ CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
//
VOID *mHashCtx = NULL;
//
// Pointer to runtime buffer.
// For "Append" operation to an existing variable, a read/modify/write operation
@ -41,19 +40,42 @@ VOID *mHashCtx = NULL;
//
VOID *mStorageArea = NULL;
//
// The serialization of the values of the VariableName, VendorGuid and Attributes
// parameters of the SetVariable() call and the TimeStamp component of the
// EFI_VARIABLE_AUTHENTICATION_2 descriptor followed by the variable's new value
// i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data)
//
UINT8 *mSerializationRuntimeBuffer = NULL;
/**
Update platform mode.
Internal function to delete a Variable given its name and GUID, no authentication
required.
@param[in] Mode SETUP_MODE or USER_MODE.
@param[in] VariableName Name of the Variable.
@param[in] VendorGuid GUID of the Variable.
@return EFI_INVALID_PARAMETER Invalid parameter.
@return EFI_SUCCESS Update platform mode successfully.
@retval EFI_SUCCESS Variable deleted successfully.
@retval Others The driver failded to start the device.
**/
EFI_STATUS
UpdatePlatformMode (
IN UINT32 Mode
);
DeleteVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid
)
{
EFI_STATUS Status;
VARIABLE_POINTER_TRACK Variable;
Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);
if (EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
ASSERT (Variable.CurrPtr != NULL);
return UpdateVariable (VariableName, VendorGuid, NULL, 0, 0, 0, 0, &Variable, NULL);
}
/**
Initializes for authenticated varibale service.
@ -69,7 +91,6 @@ AutenticatedVariableServiceInitialize (
{
EFI_STATUS Status;
VARIABLE_POINTER_TRACK Variable;
VARIABLE_POINTER_TRACK Variable2;
UINT8 VarValue;
UINT32 VarAttr;
UINT8 *Data;
@ -90,11 +111,20 @@ AutenticatedVariableServiceInitialize (
//
// Reserved runtime buffer for "Append" operation in virtual mode.
//
mStorageArea = AllocateRuntimePool (PcdGet32 (PcdMaxAppendVariableSize));
mStorageArea = AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize));
if (mStorageArea == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Prepare runtime buffer for serialized data of time-based authenticated
// Variable, i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data).
//
mSerializationRuntimeBuffer = AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize) + sizeof (EFI_GUID) + sizeof (UINT32) + sizeof (EFI_TIME));
if (mSerializationRuntimeBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Check "AuthVarKeyDatabase" variable's existence.
// If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
@ -150,16 +180,16 @@ AutenticatedVariableServiceInitialize (
Status = FindVariable (
EFI_PLATFORM_KEY_NAME,
&gEfiGlobalVariableGuid,
&Variable2,
&Variable,
&mVariableModuleGlobal->VariableGlobal
);
if (Variable2.CurrPtr == NULL) {
if (Variable.CurrPtr == NULL) {
mPlatformMode = SETUP_MODE;
} else {
mPlatformMode = USER_MODE;
}
VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
Status = UpdateVariable (
EFI_SETUP_MODE_NAME,
&gEfiGlobalVariableGuid,
@ -188,7 +218,6 @@ AutenticatedVariableServiceInitialize (
&mVariableModuleGlobal->VariableGlobal
);
if (Variable.CurrPtr == NULL) {
VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
Status = UpdateVariable (
@ -206,13 +235,35 @@ AutenticatedVariableServiceInitialize (
//
// If "SecureBootEnable" variable exists, then update "SecureBoot" variable.
// If "SecureBootEnable" variable is SECURE_BOOT_ENABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.
// If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in USER_MODE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.
// If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.
//
SecureBootEnable = SECURE_BOOT_MODE_DISABLE;
FindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);
if (Variable.CurrPtr != NULL) {
SecureBootEnable = *(GetVariableDataPtr (Variable.CurrPtr));
if (SecureBootEnable == SECURE_BOOT_ENABLE) {
} else if (mPlatformMode == USER_MODE) {
//
// "SecureBootEnable" not exist, initialize it in USER_MODE.
//
SecureBootEnable = SECURE_BOOT_MODE_ENABLE;
Status = UpdateVariable (
EFI_SECURE_BOOT_ENABLE_NAME,
&gEfiSecureBootEnableDisableGuid,
&SecureBootEnable,
sizeof (UINT8),
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
0,
0,
&Variable,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
}
if (SecureBootEnable == SECURE_BOOT_ENABLE && mPlatformMode == USER_MODE) {
SecureBootMode = SECURE_BOOT_MODE_ENABLE;
} else {
SecureBootMode = SECURE_BOOT_MODE_DISABLE;
@ -223,7 +274,7 @@ AutenticatedVariableServiceInitialize (
&gEfiGlobalVariableGuid,
&SecureBootMode,
sizeof (UINT8),
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
0,
0,
&Variable,
@ -232,7 +283,6 @@ AutenticatedVariableServiceInitialize (
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Detect whether a secure platform-specific method to clear PK(Platform Key)
@ -241,37 +291,26 @@ AutenticatedVariableServiceInitialize (
//
if (ForceClearPK ()) {
//
// 1. Check whether PK is existing, and clear PK if existing
// 1. Clear PK.
//
FindVariable (
EFI_PLATFORM_KEY_NAME,
&gEfiGlobalVariableGuid,
&Variable,
&mVariableModuleGlobal->VariableGlobal
);
if (Variable.CurrPtr != NULL) {
VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
Status = UpdateVariable (
EFI_PLATFORM_KEY_NAME,
&gEfiGlobalVariableGuid,
NULL,
0,
VarAttr,
0,
0,
&Variable,
NULL
);
Status = DeleteVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// 2. Update "SetupMode" variable to SETUP_MODE
// 2. Update "SetupMode" variable to SETUP_MODE.
//
UpdatePlatformMode (SETUP_MODE);
//
// 3. Clear KEK, DB and DBX.
//
DeleteVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid);
DeleteVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid);
DeleteVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid);
}
return Status;
}
@ -358,9 +397,9 @@ AddPubKeyInStore (
@param[in] DataSize Size of Data.
@param[in] PubKey Public key used for verification.
@return EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_SECURITY_VIOLATION If authentication failed.
@return EFI_SUCCESS Authentication successful.
@retval EFI_SUCCESS Authentication successful.
**/
EFI_STATUS
@ -461,7 +500,6 @@ Done:
}
}
/**
Update platform mode.
@ -494,7 +532,7 @@ UpdatePlatformMode (
}
mPlatformMode = Mode;
VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
Status = UpdateVariable (
EFI_SETUP_MODE_NAME,
&gEfiGlobalVariableGuid,
@ -510,6 +548,15 @@ UpdatePlatformMode (
return Status;
}
if (AtRuntime ()) {
//
// SecureBoot Variable indicates whether the platform firmware is operating
// in Secure boot mode (1) or not (0), so we should not change SecureBoot
// Variable in runtime.
//
return Status;
}
//
// Check "SecureBoot" variable's existence.
// If it doesn't exist, firmware has no capability to perform driver signing verification,
@ -538,7 +585,7 @@ UpdatePlatformMode (
}
}
VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
Status = UpdateVariable (
EFI_SECURE_BOOT_MODE_NAME,
&gEfiGlobalVariableGuid,
@ -550,7 +597,6 @@ UpdatePlatformMode (
&Variable,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
@ -633,6 +679,10 @@ ProcessVarWithPk (
EFI_VARIABLE_AUTHENTICATION *CertData;
BOOLEAN TimeBase;
BOOLEAN Del;
UINT8 *Payload;
UINTN PayloadSize;
UINT64 MonotonicCount;
EFI_TIME *TimeStamp;
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
//
@ -721,7 +771,46 @@ ProcessVarWithPk (
}
}
} else {
Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, Variable, NULL);
//
// Process PK or KEK in Setup mode.
//
if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
//
// Time-based Authentication descriptor.
//
MonotonicCount = 0;
TimeStamp = &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp;
Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);
PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
} else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
//
// Counter-based Authentication descriptor.
//
MonotonicCount = ((EFI_VARIABLE_AUTHENTICATION *) Data)->MonotonicCount;
TimeStamp = NULL;
Payload = (UINT8*) Data + AUTHINFO_SIZE;
PayloadSize = DataSize - AUTHINFO_SIZE;
} else {
//
// No Authentication descriptor.
//
MonotonicCount = 0;
TimeStamp = NULL;
Payload = Data;
PayloadSize = DataSize;
}
Status = UpdateVariable (
VariableName,
VendorGuid,
Payload,
PayloadSize,
Attributes,
0,
MonotonicCount,
Variable,
TimeStamp
);
//
// If enroll PK in setup mode, need change to user mode.
//
@ -770,6 +859,9 @@ ProcessVarWithKek (
BOOLEAN IsFound;
UINT32 Index;
UINT32 KekDataSize;
UINT8 *Payload;
UINTN PayloadSize;
UINT64 MonotonicCount;
if (mPlatformMode == USER_MODE) {
if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
@ -844,14 +936,30 @@ ProcessVarWithKek (
//
// If in setup mode, no authentication needed.
//
if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
//
// Counter-based Authentication descriptor.
//
MonotonicCount = ((EFI_VARIABLE_AUTHENTICATION *) Data)->MonotonicCount;
Payload = (UINT8*) Data + AUTHINFO_SIZE;
PayloadSize = DataSize - AUTHINFO_SIZE;
} else {
//
// No Authentication descriptor.
//
MonotonicCount = 0;
Payload = Data;
PayloadSize = DataSize;
}
Status = UpdateVariable (
VariableName,
VendorGuid,
Data,
DataSize,
Payload,
PayloadSize,
Attributes,
0,
0,
MonotonicCount,
Variable,
NULL
);
@ -1004,6 +1112,114 @@ ProcessVariable (
return UpdateVariable (VariableName, VendorGuid, (UINT8*)Data + AUTHINFO_SIZE, DataSize - AUTHINFO_SIZE, Attributes, KeyIndex, MonotonicCount, Variable, NULL);
}
/**
Merge two buffers which formatted as EFI_SIGNATURE_LIST. Only the new EFI_SIGNATURE_DATA
will be appended to the original EFI_SIGNATURE_LIST, duplicate EFI_SIGNATURE_DATA
will be ignored.
@param[in, out] Data Pointer to original EFI_SIGNATURE_LIST.
@param[in] DataSize Size of Data buffer.
@param[in] NewData Pointer to new EFI_SIGNATURE_LIST to be appended.
@param[in] NewDataSize Size of NewData buffer.
@return Size of the merged buffer.
**/
UINTN
AppendSignatureList (
IN OUT VOID *Data,
IN UINTN DataSize,
IN VOID *NewData,
IN UINTN NewDataSize
)
{
EFI_SIGNATURE_LIST *CertList;
EFI_SIGNATURE_DATA *Cert;
UINTN CertCount;
EFI_SIGNATURE_LIST *NewCertList;
EFI_SIGNATURE_DATA *NewCert;
UINTN NewCertCount;
UINTN Index;
UINTN Index2;
UINTN Size;
UINT8 *Tail;
UINTN CopiedCount;
UINTN SignatureListSize;
BOOLEAN IsNewCert;
Tail = (UINT8 *) Data + DataSize;
NewCertList = (EFI_SIGNATURE_LIST *) NewData;
while ((NewDataSize > 0) && (NewDataSize >= NewCertList->SignatureListSize)) {
NewCert = (EFI_SIGNATURE_DATA *) ((UINT8 *) NewCertList + sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize);
NewCertCount = (NewCertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - NewCertList->SignatureHeaderSize) / NewCertList->SignatureSize;
CopiedCount = 0;
for (Index = 0; Index < NewCertCount; Index++) {
IsNewCert = TRUE;
Size = DataSize;
CertList = (EFI_SIGNATURE_LIST *) Data;
while ((Size > 0) && (Size >= CertList->SignatureListSize)) {
if (CompareGuid (&CertList->SignatureType, &NewCertList->SignatureType) &&
(CertList->SignatureSize == NewCertList->SignatureSize)) {
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
for (Index2 = 0; Index2 < CertCount; Index2++) {
//
// Iterate each Signature Data in this Signature List.
//
if (CompareMem (NewCert, Cert, CertList->SignatureSize) == 0) {
IsNewCert = FALSE;
break;
}
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
}
}
if (!IsNewCert) {
break;
}
Size -= CertList->SignatureListSize;
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
}
if (IsNewCert) {
//
// New EFI_SIGNATURE_DATA, append it.
//
if (CopiedCount == 0) {
//
// Copy EFI_SIGNATURE_LIST header for only once.
//
CopyMem (Tail, NewCertList, sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize);
Tail = Tail + sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize;
}
CopyMem (Tail, NewCert, NewCertList->SignatureSize);
Tail += NewCertList->SignatureSize;
CopiedCount++;
}
NewCert = (EFI_SIGNATURE_DATA *) ((UINT8 *) NewCert + NewCertList->SignatureSize);
}
//
// Update SignatureListSize in newly appended EFI_SIGNATURE_LIST.
//
if (CopiedCount != 0) {
SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize + (CopiedCount * NewCertList->SignatureSize);
CertList = (EFI_SIGNATURE_LIST *) (Tail - SignatureListSize);
CertList->SignatureListSize = (UINT32) SignatureListSize;
}
NewDataSize -= NewCertList->SignatureListSize;
NewCertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) NewCertList + NewCertList->SignatureListSize);
}
return (Tail - (UINT8 *) Data);
}
/**
Compare two EFI_TIME data.
@ -1071,11 +1287,11 @@ VerifyTimeBasedPayload (
{
UINT8 *RootCert;
UINT8 *SigData;
UINT8 *PayLoadPtr;
UINT8 *PayloadPtr;
UINTN RootCertSize;
UINTN Index;
UINTN CertCount;
UINTN PayLoadSize;
UINTN PayloadSize;
UINT32 Attr;
UINT32 SigDataSize;
UINT32 KekDataSize;
@ -1089,7 +1305,8 @@ VerifyTimeBasedPayload (
UINT8 *NewData;
UINTN NewDataSize;
VARIABLE_POINTER_TRACK PkVariable;
UINT8 *Buffer;
UINTN Length;
Result = FALSE;
VerifyStatus = FALSE;
@ -1107,6 +1324,18 @@ VerifyTimeBasedPayload (
//
CertData = (EFI_VARIABLE_AUTHENTICATION_2 *) Data;
//
// Verify that Pad1, Nanosecond, TimeZone, Daylight and Pad2 components of the
// TimeStamp value are set to zero.
//
if ((CertData->TimeStamp.Pad1 != 0) ||
(CertData->TimeStamp.Nanosecond != 0) ||
(CertData->TimeStamp.TimeZone != 0) ||
(CertData->TimeStamp.Daylight != 0) ||
(CertData->TimeStamp.Pad2 != 0)) {
return EFI_INVALID_PARAMETER;
}
if ((Variable->CurrPtr != NULL) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {
if (CompareTimeStamp (&CertData->TimeStamp, &Variable->CurrPtr->TimeStamp)) {
//
@ -1121,8 +1350,7 @@ VerifyTimeBasedPayload (
// Cert type should be EFI_CERT_TYPE_PKCS7_GUID.
//
if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
!CompareGuid (&CertData->AuthInfo.CertType, &gEfiCertPkcs7Guid)
) {
!CompareGuid (&CertData->AuthInfo.CertType, &gEfiCertPkcs7Guid)) {
//
// Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
//
@ -1133,63 +1361,40 @@ VerifyTimeBasedPayload (
// Find out Pkcs7 SignedData which follows the EFI_VARIABLE_AUTHENTICATION_2 descriptor.
// AuthInfo.Hdr.dwLength is the length of the entire certificate, including the length of the header.
//
SigData = (UINT8*) ((UINTN)Data + OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData));
//
// Sanity check to avoid corrupted certificate input.
//
if (CertData->AuthInfo.Hdr.dwLength < (UINT32)(OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData))) {
return EFI_SECURITY_VIOLATION;
}
SigData = CertData->AuthInfo.CertData;
SigDataSize = CertData->AuthInfo.Hdr.dwLength - (UINT32) (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData));
//
// Find out the new data payload which follows Pkcs7 SignedData directly.
//
PayLoadPtr = (UINT8*) ((UINTN) SigData + (UINTN) SigDataSize);
//
// Sanity check to avoid corrupted certificate input.
//
if (DataSize < (OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)+ (UINTN) SigDataSize)) {
return EFI_SECURITY_VIOLATION;
}
PayLoadSize = DataSize - OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) - OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData) - (UINTN) SigDataSize;
PayloadPtr = SigData + SigDataSize;
PayloadSize = DataSize - OFFSET_OF_AUTHINFO2_CERT_DATA - (UINTN) SigDataSize;
//
// Construct a buffer to fill with (VariableName, VendorGuid, Attributes, TimeStamp, Data).
//
NewDataSize = PayLoadSize + sizeof (EFI_TIME) + sizeof (UINT32) +
sizeof (EFI_GUID) + StrSize (VariableName);
NewData = (UINT8 *) AllocateZeroPool (NewDataSize);
NewDataSize = PayloadSize + sizeof (EFI_TIME) + sizeof (UINT32) +
sizeof (EFI_GUID) + StrSize (VariableName) - sizeof (CHAR16);
NewData = mSerializationRuntimeBuffer;
if (NewData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Buffer = NewData;
Length = StrLen (VariableName) * sizeof (CHAR16);
CopyMem (Buffer, VariableName, Length);
Buffer += Length;
CopyMem (NewData, VariableName, StrSize (VariableName));
Length = sizeof (EFI_GUID);
CopyMem (Buffer, VendorGuid, Length);
Buffer += Length;
CopyMem (NewData + StrSize (VariableName), VendorGuid, sizeof (EFI_GUID));
Length = sizeof (UINT32);
CopyMem (Buffer, &Attr, Length);
Buffer += Length;
CopyMem (
NewData + StrSize (VariableName) + sizeof (EFI_GUID),
&Attr,
sizeof (UINT32)
);
CopyMem (
NewData + StrSize (VariableName) + sizeof (EFI_GUID) + sizeof (UINT32),
&CertData->TimeStamp,
sizeof (EFI_TIME)
);
CopyMem (NewData + (NewDataSize - PayLoadSize), PayLoadPtr, PayLoadSize);
Length = sizeof (EFI_TIME);
CopyMem (Buffer, &CertData->TimeStamp, Length);
Buffer += Length;
CopyMem (Buffer, PayloadPtr, PayloadSize);
if (Pk) {
//
@ -1278,13 +1483,11 @@ VerifyTimeBasedPayload (
Exit:
FreePool (NewData);
if (!VerifyStatus) {
return EFI_SECURITY_VIOLATION;
}
if ((PayLoadSize == 0) && (VarDel != NULL)) {
if ((PayloadSize == 0) && (VarDel != NULL)) {
*VarDel = TRUE;
}
@ -1294,8 +1497,8 @@ Exit:
return UpdateVariable (
VariableName,
VendorGuid,
PayLoadPtr,
PayLoadSize,
PayloadPtr,
PayloadSize,
Attributes,
0,
0,

View File

@ -20,9 +20,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define EFI_CERT_TYPE_RSA2048_SIZE 256
///
/// Size of AuthInfo prior to the data payload
/// Size of AuthInfo prior to the data payload.
///
#define AUTHINFO_SIZE (((UINTN)(((EFI_VARIABLE_AUTHENTICATION *) 0)->AuthInfo.CertData)) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256))
#define AUTHINFO_SIZE ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \
(OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) + \
sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256))
#define AUTHINFO2_SIZE(VarAuth2) ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \
(UINTN) ((EFI_VARIABLE_AUTHENTICATION_2 *) (VarAuth2))->AuthInfo.Hdr.dwLength)
#define OFFSET_OF_AUTHINFO2_CERT_DATA ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \
(OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)))
///
/// "AuthVarKeyDatabase" variable for the Public Key store.
@ -73,6 +81,20 @@ ProcessVariable (
IN UINT32 Attributes
);
/**
Update platform mode.
@param[in] Mode SETUP_MODE or USER_MODE.
@return EFI_INVALID_PARAMETER Invalid parameter.
@return EFI_SUCCESS Update platform mode successfully.
**/
EFI_STATUS
UpdatePlatformMode (
IN UINT32 Mode
);
/**
Initializes for authenticated varibale service.
@ -150,6 +172,27 @@ ProcessVarWithKek (
IN UINT32 Attributes OPTIONAL
);
/**
Merge two buffers which formatted as EFI_SIGNATURE_LIST. Only the new EFI_SIGNATURE_DATA
will be appended to the original EFI_SIGNATURE_LIST, duplicate EFI_SIGNATURE_DATA
will be ignored.
@param[in, out] Data Pointer to original EFI_SIGNATURE_LIST.
@param[in] DataSize Size of Data buffer.
@param[in] NewData Pointer to new EFI_SIGNATURE_LIST to be appended.
@param[in] NewDataSize Size of NewData buffer.
@return Size of the merged buffer.
**/
UINTN
AppendSignatureList (
IN OUT VOID *Data,
IN UINTN DataSize,
IN VOID *NewData,
IN UINTN NewDataSize
);
/**
Compare two EFI_TIME data.
@ -205,5 +248,6 @@ extern UINT8 mPubKeyStore[MAX_KEYDB_SIZE];
extern UINT32 mPubKeyNumber;
extern VOID *mHashCtx;
extern VOID *mStorageArea;
extern UINT8 *mSerializationRuntimeBuffer;
#endif

View File

@ -1491,8 +1491,11 @@ UpdateVariable (
//
if (DataSizeOfVariable (Variable->CurrPtr) == DataSize &&
(CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0) &&
((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {
((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) &&
(TimeStamp == NULL)) {
//
// Variable content unchanged and no need to update timestamp, just return.
//
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
Status = EFI_SUCCESS;
goto Done;
@ -1503,10 +1506,40 @@ UpdateVariable (
// EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable
//
if ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0) {
//
// Cache the previous variable data into StorageArea.
//
DataOffset = sizeof (VARIABLE_HEADER) + Variable->CurrPtr->NameSize + GET_PAD_SIZE (Variable->CurrPtr->NameSize);
CopyMem (mStorageArea, (UINT8*)((UINTN) Variable->CurrPtr + DataOffset), Variable->CurrPtr->DataSize);
if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) ||
(CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {
//
// For variables with the GUID EFI_IMAGE_SECURITY_DATABASE_GUID (i.e. where the data
// buffer is formatted as EFI_SIGNATURE_LIST), the driver shall not perform an append of
// EFI_SIGNATURE_DATA values that are already part of the existing variable value.
//
BufSize = AppendSignatureList (mStorageArea, Variable->CurrPtr->DataSize, Data, DataSize);
if (BufSize == Variable->CurrPtr->DataSize) {
if ((TimeStamp == NULL) || CompareTimeStamp (TimeStamp, &Variable->CurrPtr->TimeStamp)) {
//
// New EFI_SIGNATURE_DATA is not found and timestamp is not later
// than current timestamp, return EFI_SUCCESS directly.
//
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
Status = EFI_SUCCESS;
goto Done;
}
}
} else {
//
// For other Variables, append the new data to the end of previous data.
//
CopyMem ((UINT8*)((UINTN) mStorageArea + Variable->CurrPtr->DataSize), Data, DataSize);
BufSize = Variable->CurrPtr->DataSize + DataSize;
RevBufSize = MIN (PcdGet32 (PcdMaxAppendVariableSize), ScratchDataSize);
}
RevBufSize = MIN (PcdGet32 (PcdMaxVariableSize), ScratchDataSize);
if (BufSize > RevBufSize) {
//
// If variable size (previous + current) is bigger than reserved buffer in runtime,
@ -1515,18 +1548,6 @@ UpdateVariable (
return EFI_OUT_OF_RESOURCES;
}
SetMem (mStorageArea, PcdGet32 (PcdMaxAppendVariableSize), 0xff);
//
// Cache the previous variable data into StorageArea.
//
DataOffset = sizeof (VARIABLE_HEADER) + Variable->CurrPtr->NameSize + GET_PAD_SIZE (Variable->CurrPtr->NameSize);
CopyMem (mStorageArea, (UINT8*)((UINTN)Variable->CurrPtr + DataOffset), Variable->CurrPtr->DataSize);
//
// Append the new data to the end of previous data.
//
CopyMem ((UINT8*)((UINTN)mStorageArea + Variable->CurrPtr->DataSize), Data, DataSize);
//
// Override Data and DataSize which are used for combined data area including previous and new data.
//
@ -1561,11 +1582,8 @@ UpdateVariable (
// Not found existing variable. Create a new variable.
//
//
// EFI_VARIABLE_APPEND_WRITE attribute only set for existing variable
//
if ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0) {
Status = EFI_INVALID_PARAMETER;
if ((DataSize == 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0)) {
Status = EFI_SUCCESS;
goto Done;
}
@ -1601,10 +1619,10 @@ UpdateVariable (
NextVariable->Reserved = 0;
NextVariable->PubKeyIndex = KeyIndex;
NextVariable->MonotonicCount = MonotonicCount;
SetMem (&NextVariable->TimeStamp, sizeof (EFI_TIME), 0);
ZeroMem (&NextVariable->TimeStamp, sizeof (EFI_TIME));
if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&
TimeStamp != NULL) {
(TimeStamp != NULL)) {
if ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) {
CopyMem (&NextVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));
} else {
@ -1613,11 +1631,13 @@ UpdateVariable (
// when the new TimeStamp value is later than the current timestamp associated
// with the variable, we need associate the new timestamp with the updated value.
//
if (Variable->CurrPtr != NULL) {
if (CompareTimeStamp (&Variable->CurrPtr->TimeStamp, TimeStamp)) {
CopyMem (&NextVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));
}
}
}
}
//
// The EFI_VARIABLE_APPEND_WRITE attribute will never be set in the returned
@ -2125,7 +2145,7 @@ VariableServiceSetVariable (
// EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS and EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute
// cannot be set both.
//
if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) \
if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
&& ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
return EFI_INVALID_PARAMETER;
}
@ -2133,14 +2153,25 @@ VariableServiceSetVariable (
if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) {
if (DataSize < AUTHINFO_SIZE) {
//
// Try to write Authencated Variable without AuthInfo.
// Try to write Authenticated Variable without AuthInfo.
//
return EFI_SECURITY_VIOLATION;
}
PayloadSize = DataSize - AUTHINFO_SIZE;
} else if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
//
// Sanity check for EFI_VARIABLE_AUTHENTICATION_2 descriptor.
//
if (DataSize < OFFSET_OF_AUTHINFO2_CERT_DATA ||
DataSize < AUTHINFO2_SIZE (Data) ||
((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->AuthInfo.Hdr.dwLength < OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) {
return EFI_SECURITY_VIOLATION;
}
PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
} else {
PayloadSize = DataSize;
}
//
// The size of the VariableName, including the Unicode Null in bytes plus
// the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)

View File

@ -234,6 +234,7 @@ VariableClassAddressChangeEvent (
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
EfiConvertPointer (0x0, (VOID **) &mHashCtx);
EfiConvertPointer (0x0, (VOID **) &mStorageArea);
EfiConvertPointer (0x0, (VOID **) &mSerializationRuntimeBuffer);
EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
}

View File

@ -82,7 +82,6 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
gEfiSecurityPkgTokenSpaceGuid.PcdMaxAppendVariableSize
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)

View File

@ -87,7 +87,6 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
gEfiSecurityPkgTokenSpaceGuid.PcdMaxAppendVariableSize
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)