mirror of https://github.com/acidanthera/audk.git
Update auth-variable and secure boot UI driver to support only time-based PK, KEK and Signature Database variable variable according to UEFI Spec requirement.
Signed-off-by: Fu Siyuan <siyuan.fu@intel.com> Reviewed-by: Dong Guo <guo.dong@intel.com> Reviewed-by: Ye Ting <ting.ye@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13310 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
82a1e09c83
commit
8c1babfd28
|
@ -879,151 +879,49 @@ ProcessVarWithPk (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VARIABLE_POINTER_TRACK PkVariable;
|
||||
EFI_SIGNATURE_LIST *OldPkList;
|
||||
EFI_SIGNATURE_DATA *OldPkData;
|
||||
EFI_VARIABLE_AUTHENTICATION *CertData;
|
||||
BOOLEAN TimeBase;
|
||||
BOOLEAN Del;
|
||||
UINT8 *Payload;
|
||||
UINTN PayloadSize;
|
||||
UINT64 MonotonicCount;
|
||||
EFI_TIME *TimeStamp;
|
||||
|
||||
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
|
||||
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 ||
|
||||
(Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {
|
||||
//
|
||||
// PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
|
||||
// PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute and should be a time-based
|
||||
// authenticated variable.
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) {
|
||||
|
||||
if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
||||
//
|
||||
// Verify against X509 Cert PK.
|
||||
//
|
||||
Del = FALSE;
|
||||
Status = VerifyTimeBasedPayload (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
Data,
|
||||
DataSize,
|
||||
Variable,
|
||||
Attributes,
|
||||
AuthVarTypePk,
|
||||
&Del
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute means time-based X509 Cert PK.
|
||||
// If delete PK in user mode, need change to setup mode.
|
||||
//
|
||||
TimeBase = TRUE;
|
||||
} else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
||||
//
|
||||
// EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute means counter-based RSA-2048 Cert PK.
|
||||
//
|
||||
TimeBase = FALSE;
|
||||
} else {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (TimeBase) {
|
||||
//
|
||||
// Verify against X509 Cert PK.
|
||||
//
|
||||
Del = FALSE;
|
||||
Status = VerifyTimeBasedPayload (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
Data,
|
||||
DataSize,
|
||||
Variable,
|
||||
Attributes,
|
||||
AuthVarTypePk,
|
||||
&Del
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// If delete PK in user mode, need change to setup mode.
|
||||
//
|
||||
if (Del && IsPk) {
|
||||
Status = UpdatePlatformMode (SETUP_MODE);
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
} else {
|
||||
//
|
||||
// Verify against RSA2048 Cert PK.
|
||||
//
|
||||
CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
|
||||
if ((Variable->CurrPtr != NULL) && (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount)) {
|
||||
//
|
||||
// Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
|
||||
//
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
//
|
||||
// Get platform key from variable.
|
||||
//
|
||||
Status = FindVariable (
|
||||
EFI_PLATFORM_KEY_NAME,
|
||||
&gEfiGlobalVariableGuid,
|
||||
&PkVariable,
|
||||
&mVariableModuleGlobal->VariableGlobal,
|
||||
FALSE
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
OldPkList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (PkVariable.CurrPtr);
|
||||
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,
|
||||
(UINT8*)Data + AUTHINFO_SIZE,
|
||||
DataSize - AUTHINFO_SIZE,
|
||||
Attributes,
|
||||
0,
|
||||
CertData->MonotonicCount,
|
||||
Variable,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// If delete PK in user mode, need change to setup mode.
|
||||
//
|
||||
if ((DataSize == AUTHINFO_SIZE) && IsPk) {
|
||||
Status = UpdatePlatformMode (SETUP_MODE);
|
||||
}
|
||||
}
|
||||
if (Del && IsPk) {
|
||||
Status = UpdatePlatformMode (SETUP_MODE);
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
} else {
|
||||
//
|
||||
// Process PK or KEK in Setup mode or Custom Secure Boot 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;
|
||||
}
|
||||
Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);
|
||||
PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
|
||||
|
||||
Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
@ -1037,9 +935,9 @@ ProcessVarWithPk (
|
|||
PayloadSize,
|
||||
Attributes,
|
||||
0,
|
||||
MonotonicCount,
|
||||
0,
|
||||
Variable,
|
||||
TimeStamp
|
||||
&((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp
|
||||
);
|
||||
|
||||
if (IsPk) {
|
||||
|
@ -1088,148 +986,39 @@ ProcessVarWithKek (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VARIABLE_POINTER_TRACK KekVariable;
|
||||
EFI_SIGNATURE_LIST *KekList;
|
||||
EFI_SIGNATURE_DATA *KekItem;
|
||||
UINT32 KekCount;
|
||||
EFI_VARIABLE_AUTHENTICATION *CertData;
|
||||
EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
|
||||
BOOLEAN IsFound;
|
||||
UINT32 Index;
|
||||
UINT32 KekDataSize;
|
||||
UINT8 *Payload;
|
||||
UINTN PayloadSize;
|
||||
UINT64 MonotonicCount;
|
||||
EFI_TIME *TimeStamp;
|
||||
|
||||
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
|
||||
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 ||
|
||||
(Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {
|
||||
//
|
||||
// DB and DBX should set EFI_VARIABLE_NON_VOLATILE attribute.
|
||||
// DB and DBX should set EFI_VARIABLE_NON_VOLATILE attribute and should be a time-based
|
||||
// authenticated variable.
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) {
|
||||
if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) &&
|
||||
((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0)){
|
||||
//
|
||||
// In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS or
|
||||
// EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute.
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
||||
//
|
||||
// Time-based, verify against X509 Cert KEK.
|
||||
//
|
||||
return VerifyTimeBasedPayload (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
Data,
|
||||
DataSize,
|
||||
Variable,
|
||||
Attributes,
|
||||
AuthVarTypeKek,
|
||||
NULL
|
||||
);
|
||||
} else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
||||
//
|
||||
// Counter-based, verify against RSA2048 Cert KEK.
|
||||
//
|
||||
CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
|
||||
CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
|
||||
if ((Variable->CurrPtr != NULL) && (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount)) {
|
||||
//
|
||||
// Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
|
||||
//
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
//
|
||||
// Get KEK database from variable.
|
||||
//
|
||||
Status = FindVariable (
|
||||
EFI_KEY_EXCHANGE_KEY_NAME,
|
||||
&gEfiGlobalVariableGuid,
|
||||
&KekVariable,
|
||||
&mVariableModuleGlobal->VariableGlobal,
|
||||
FALSE
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
KekDataSize = KekVariable.CurrPtr->DataSize;
|
||||
KekList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (KekVariable.CurrPtr);
|
||||
|
||||
//
|
||||
// Enumerate all Kek items in this list to verify the variable certificate data.
|
||||
// If anyone is authenticated successfully, it means the variable is correct!
|
||||
//
|
||||
IsFound = FALSE;
|
||||
while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) {
|
||||
if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) {
|
||||
KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);
|
||||
KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;
|
||||
for (Index = 0; Index < KekCount; Index++) {
|
||||
if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
|
||||
IsFound = TRUE;
|
||||
break;
|
||||
}
|
||||
KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);
|
||||
}
|
||||
}
|
||||
KekDataSize -= KekList->SignatureListSize;
|
||||
KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);
|
||||
}
|
||||
|
||||
if (!IsFound) {
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
|
||||
Status = VerifyCounterBasedPayload (Data, DataSize, CertBlock->PublicKey);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = UpdateVariable (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
(UINT8*)Data + AUTHINFO_SIZE,
|
||||
DataSize - AUTHINFO_SIZE,
|
||||
Attributes,
|
||||
0,
|
||||
CertData->MonotonicCount,
|
||||
Variable,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Time-based, verify against X509 Cert KEK.
|
||||
//
|
||||
return VerifyTimeBasedPayload (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
Data,
|
||||
DataSize,
|
||||
Variable,
|
||||
Attributes,
|
||||
AuthVarTypeKek,
|
||||
NULL
|
||||
);
|
||||
} else {
|
||||
//
|
||||
// If in setup mode or custom secure boot mode, no authentication needed.
|
||||
//
|
||||
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;
|
||||
}
|
||||
Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);
|
||||
PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
|
||||
|
||||
Status = UpdateVariable (
|
||||
VariableName,
|
||||
|
@ -1238,9 +1027,9 @@ ProcessVarWithKek (
|
|||
PayloadSize,
|
||||
Attributes,
|
||||
0,
|
||||
MonotonicCount,
|
||||
0,
|
||||
Variable,
|
||||
TimeStamp
|
||||
&((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
gEfiCustomModeEnableGuid
|
||||
gEfiSecureBootEnableDisableGuid
|
||||
gSecureBootConfigFormSetGuid
|
||||
gEfiCertPkcs7Guid
|
||||
gEfiCertRsa2048Guid ## CONSUMES
|
||||
gEfiCertX509Guid ## CONSUMES
|
||||
gEfiCertSha1Guid ## CONSUMES
|
||||
|
|
|
@ -108,6 +108,90 @@ SaveSecureBootVariable (
|
|||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
|
||||
descriptor with the input data. NO authentication is required in this function.
|
||||
|
||||
@param[in, out] DataSize On input, the size of Data buffer in bytes.
|
||||
On output, the size of data returned in Data
|
||||
buffer in bytes.
|
||||
@param[in, out] Data On input, Pointer to data buffer to be wrapped or
|
||||
pointer to NULL to wrap an empty payload.
|
||||
On output, Pointer to the new payload date buffer allocated from pool,
|
||||
it's caller's responsibility to free the memory when finish using it.
|
||||
|
||||
@retval EFI_SUCCESS Create time based payload successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid.
|
||||
@retval Others Unexpected error happens.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
CreateTimeBasedPayload (
|
||||
IN OUT UINTN *DataSize,
|
||||
IN OUT UINT8 **Data
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 *NewData;
|
||||
UINT8 *Payload;
|
||||
UINTN PayloadSize;
|
||||
EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;
|
||||
UINTN DescriptorSize;
|
||||
EFI_TIME Time;
|
||||
|
||||
if (Data == NULL || DataSize == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// In Setup mode or Custom mode, the variable does not need to be signed but the
|
||||
// parameters to the SetVariable() call still need to be prepared as authenticated
|
||||
// variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
|
||||
// data in it.
|
||||
//
|
||||
Payload = *Data;
|
||||
PayloadSize = *DataSize;
|
||||
|
||||
DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
|
||||
NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
|
||||
if (NewData == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if ((Payload != NULL) && (PayloadSize != 0)) {
|
||||
CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
|
||||
}
|
||||
|
||||
DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
|
||||
|
||||
ZeroMem (&Time, sizeof (EFI_TIME));
|
||||
Status = gRT->GetTime (&Time, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool(NewData);
|
||||
return Status;
|
||||
}
|
||||
Time.Pad1 = 0;
|
||||
Time.Nanosecond = 0;
|
||||
Time.TimeZone = 0;
|
||||
Time.Daylight = 0;
|
||||
Time.Pad2 = 0;
|
||||
CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
|
||||
|
||||
DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
|
||||
DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;
|
||||
DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
|
||||
CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
|
||||
|
||||
if (Payload != NULL) {
|
||||
FreePool(Payload);
|
||||
}
|
||||
|
||||
*DataSize = DescriptorSize + PayloadSize;
|
||||
*Data = NewData;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Internal helper function to delete a Variable given its name and GUID, NO authentication
|
||||
required.
|
||||
|
@ -127,130 +211,36 @@ DeleteVariable (
|
|||
{
|
||||
EFI_STATUS Status;
|
||||
VOID* Variable;
|
||||
UINT8 *Data;
|
||||
UINTN DataSize;
|
||||
UINT32 Attr;
|
||||
|
||||
Variable = GetVariable (VariableName, VendorGuid);
|
||||
if (Variable == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Status = gRT->SetVariable (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
Data = NULL;
|
||||
DataSize = 0;
|
||||
Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
|
||||
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
|
||||
|
||||
/**
|
||||
Generate a PK signature list from the public key storing file (*.pbk).
|
||||
|
||||
@param[in] PkKeyFile FileHandle of the public key storing file.
|
||||
@param[out] PkCert Point to the data buffer to store the signature list.
|
||||
|
||||
@return EFI_UNSUPPORTED Unsupported Key Length.
|
||||
@return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
CreatePkRsaSignatureList (
|
||||
IN EFI_FILE_HANDLE PkKeyFile,
|
||||
OUT EFI_SIGNATURE_LIST **PkCert
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN KeyBlobSize;
|
||||
VOID *KeyBlob;
|
||||
CPL_KEY_INFO *KeyInfo;
|
||||
EFI_SIGNATURE_DATA *PkCertData;
|
||||
VOID *KeyBuffer;
|
||||
UINTN KeyLenInBytes;
|
||||
|
||||
PkCertData = NULL;
|
||||
KeyBlob = NULL;
|
||||
KeyBuffer = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Get key from PK key file
|
||||
//
|
||||
Status = ReadFileContent (PkKeyFile, &KeyBlob, &KeyBlobSize, 0);
|
||||
if (EFI_ERROR(Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Can't Open the file for PK enrolling.\n"));
|
||||
goto ON_EXIT;
|
||||
}
|
||||
ASSERT (KeyBlob != NULL);
|
||||
|
||||
KeyInfo = (CPL_KEY_INFO *)KeyBlob;
|
||||
if (KeyInfo->KeyLengthInBits/8 != WIN_CERT_UEFI_RSA2048_SIZE) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto ON_EXIT;
|
||||
Status = CreateTimeBasedPayload (&DataSize, &Data);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Convert the Public key to fix octet string format represented in RSA PKCS#1.
|
||||
//
|
||||
KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;
|
||||
KeyBuffer = AllocateZeroPool(KeyLenInBytes);
|
||||
if (KeyBuffer == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
Status = gRT->SetVariable (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
Attr,
|
||||
DataSize,
|
||||
Data
|
||||
);
|
||||
if (Data != NULL) {
|
||||
FreePool (Data);
|
||||
}
|
||||
Status = Int2OctStr (
|
||||
(UINTN*) ((UINTN)KeyBlob + sizeof(CPL_KEY_INFO)),
|
||||
KeyLenInBytes / sizeof (UINTN),
|
||||
(UINT8*)KeyBuffer,
|
||||
KeyLenInBytes
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
// Allocate space for PK certificate list and initialize the list.
|
||||
// Create PK database entry with SignatureHeaderSize equals 0.
|
||||
//
|
||||
*PkCert = (EFI_SIGNATURE_LIST*)AllocateZeroPool(
|
||||
sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1
|
||||
+ WIN_CERT_UEFI_RSA2048_SIZE
|
||||
);
|
||||
|
||||
if (*PkCert == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
(*PkCert)->SignatureListSize = sizeof(EFI_SIGNATURE_LIST)
|
||||
+ sizeof(EFI_SIGNATURE_DATA) - 1
|
||||
+ WIN_CERT_UEFI_RSA2048_SIZE;
|
||||
(*PkCert)->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;
|
||||
(*PkCert)->SignatureHeaderSize = 0;
|
||||
CopyGuid (&(*PkCert)->SignatureType, &gEfiCertRsa2048Guid);
|
||||
|
||||
PkCertData = (EFI_SIGNATURE_DATA*)((UINTN)(*PkCert)
|
||||
+ sizeof(EFI_SIGNATURE_LIST)
|
||||
+ (*PkCert)->SignatureHeaderSize);
|
||||
CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);
|
||||
//
|
||||
// Fill the PK database with PKpub data from PKKeyFile.
|
||||
//
|
||||
CopyMem (&(PkCertData->SignatureData[0]), KeyBuffer, WIN_CERT_UEFI_RSA2048_SIZE);
|
||||
|
||||
ON_EXIT:
|
||||
|
||||
if (KeyBlob != NULL) {
|
||||
FreePool (KeyBlob);
|
||||
}
|
||||
|
||||
if (EFI_ERROR(Status) && *PkCert != NULL) {
|
||||
FreePool (*PkCert);
|
||||
*PkCert = NULL;
|
||||
}
|
||||
|
||||
if (KeyBuffer != NULL) {
|
||||
FreePool (KeyBuffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -357,11 +347,11 @@ EnrollPlatformKey (
|
|||
PkCert = NULL;
|
||||
|
||||
//
|
||||
// Parse the file's postfix. Only support *.pbk(RSA2048) and *.cer(X509) files.
|
||||
// Parse the file's postfix. Only support *.cer(X509) files.
|
||||
//
|
||||
FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;
|
||||
if (CompareMem (FilePostFix, L".pbk",4) && CompareMem (FilePostFix, L".cer",4)) {
|
||||
DEBUG ((EFI_D_ERROR, "Don't support the file, only *.pbk or *.cer.\n is supported."));
|
||||
if (CompareMem (FilePostFix, L".cer",4)) {
|
||||
DEBUG ((EFI_D_ERROR, "Don't support the file, only *.cer is supported."));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));
|
||||
|
@ -370,22 +360,12 @@ EnrollPlatformKey (
|
|||
//
|
||||
// Prase the selected PK file and generature PK certificate list.
|
||||
//
|
||||
if (!CompareMem (FilePostFix, L".pbk",4)) {
|
||||
Status = CreatePkRsaSignatureList (
|
||||
Private->FileContext->FHandle,
|
||||
&PkCert
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
} else if (!CompareMem (FilePostFix, L".cer",4)) {
|
||||
Status = CreatePkX509SignatureList (
|
||||
Private->FileContext->FHandle,
|
||||
&PkCert
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
Status = CreatePkX509SignatureList (
|
||||
Private->FileContext->FHandle,
|
||||
&PkCert
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
ASSERT (PkCert != NULL);
|
||||
|
||||
|
@ -393,8 +373,14 @@ EnrollPlatformKey (
|
|||
// Set Platform Key variable.
|
||||
//
|
||||
Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS;
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
|
||||
DataSize = PkCert->SignatureListSize;
|
||||
Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = gRT->SetVariable(
|
||||
EFI_PLATFORM_KEY_NAME,
|
||||
&gEfiGlobalVariableGuid,
|
||||
|
@ -437,8 +423,10 @@ DeletePlatformKey (
|
|||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = DeleteVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid);
|
||||
|
||||
Status = DeleteVariable (
|
||||
EFI_PLATFORM_KEY_NAME,
|
||||
&gEfiGlobalVariableGuid
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -551,8 +539,14 @@ EnrollRsa2048ToKek (
|
|||
// If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
|
||||
// new KEK to original variable.
|
||||
//
|
||||
Attr |= EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS;
|
||||
DataSize = 0;
|
||||
Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
|
||||
Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = gRT->GetVariable(
|
||||
EFI_KEY_EXCHANGE_KEY_NAME,
|
||||
&gEfiGlobalVariableGuid,
|
||||
|
@ -672,8 +666,13 @@ EnrollX509ToKek (
|
|||
// new kek to original variable
|
||||
//
|
||||
Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS;
|
||||
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
|
||||
Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = gRT->GetVariable(
|
||||
EFI_KEY_EXCHANGE_KEY_NAME,
|
||||
&gEfiGlobalVariableGuid,
|
||||
|
@ -826,7 +825,12 @@ EnrollX509toSigDB (
|
|||
// new signature data to original variable
|
||||
//
|
||||
Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS;
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
|
||||
Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = gRT->GetVariable(
|
||||
VariableName,
|
||||
|
@ -1281,8 +1285,6 @@ EnrollImageSignatureToSigDB (
|
|||
|
||||
Data = NULL;
|
||||
GuidCertData = NULL;
|
||||
Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS;
|
||||
|
||||
//
|
||||
// Form the SigDB certificate list.
|
||||
|
@ -1374,6 +1376,14 @@ EnrollImageSignatureToSigDB (
|
|||
CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
|
||||
CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);
|
||||
|
||||
Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
|
||||
Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if SigDB variable has been already existed.
|
||||
// If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
|
||||
|
@ -1799,8 +1809,14 @@ DeleteKeyExchangeKey (
|
|||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||
}
|
||||
|
||||
CertList = (EFI_SIGNATURE_LIST*) OldData;
|
||||
DataSize = Offset;
|
||||
if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
||||
Status = CreateTimeBasedPayload (&DataSize, &OldData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
Status = gRT->SetVariable(
|
||||
EFI_KEY_EXCHANGE_KEY_NAME,
|
||||
|
@ -1986,8 +2002,14 @@ DeleteSignature (
|
|||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||
}
|
||||
|
||||
CertList = (EFI_SIGNATURE_LIST*) OldData;
|
||||
DataSize = Offset;
|
||||
if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
|
||||
Status = CreateTimeBasedPayload (&DataSize, &OldData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
Status = gRT->SetVariable(
|
||||
VariableName,
|
||||
|
@ -2465,7 +2487,7 @@ SecureBootCallback (
|
|||
CreatePopUp (
|
||||
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
||||
&Key,
|
||||
L"ERROR: The File Type is neither *.cer nor *.pbk!",
|
||||
L"ERROR: Unsupported file type, only *.cer is supported!",
|
||||
NULL
|
||||
);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue