UEFI 2.4 X509 Certificate Hash and RFC3161 Timestamp Verification support for Secure Boot
Main ChangeLogs includes: 1. Introduce the new GUID and structure definitions for certificate hash and timestamp support; 2. Update Image Verification Library to support DBT signature checking; 3. Update the related SecureBoot Configuration Pages; Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Qin Long <qin.long@intel.com> Reviewed-by: Guo Dong <guo.dong@intel.com> Reviewed-by: Siyuan Fu <siyuan.fu@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16380 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
Image signature database are defined for the signed image validation.
|
||||
|
||||
Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
@ -11,13 +11,14 @@
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
@par Revision Reference:
|
||||
GUIDs defined in UEFI 2.3.1 spec.
|
||||
GUIDs defined in UEFI 2.4 spec.
|
||||
**/
|
||||
|
||||
#ifndef __IMAGE_AUTHTICATION_H__
|
||||
#define __IMAGE_AUTHTICATION_H__
|
||||
|
||||
#include <Guid/GlobalVariable.h>
|
||||
#include <Protocol/Hash.h>
|
||||
|
||||
#define EFI_IMAGE_SECURITY_DATABASE_GUID \
|
||||
{ \
|
||||
@ -34,6 +35,11 @@
|
||||
/// for the forbidden signature database.
|
||||
///
|
||||
#define EFI_IMAGE_SECURITY_DATABASE1 L"dbx"
|
||||
///
|
||||
/// Variable name with guid EFI_IMAGE_SECURITY_DATABASE_GUID
|
||||
/// for the timestamp signature database.
|
||||
///
|
||||
#define EFI_IMAGE_SECURITY_DATABASE2 L"dbt"
|
||||
|
||||
#define SECURE_BOOT_MODE_ENABLE 1
|
||||
#define SECURE_BOOT_MODE_DISABLE 0
|
||||
@ -87,6 +93,39 @@ typedef struct {
|
||||
///
|
||||
} EFI_SIGNATURE_LIST;
|
||||
|
||||
typedef struct {
|
||||
///
|
||||
/// The SHA256 hash of an X.509 certificate's To-Be-Signed contents.
|
||||
///
|
||||
EFI_SHA256_HASH ToBeSignedHash;
|
||||
///
|
||||
/// The time that the certificate shall be considered to be revoked.
|
||||
///
|
||||
EFI_TIME TimeOfRevocation;
|
||||
} EFI_CERT_X509_SHA256;
|
||||
|
||||
typedef struct {
|
||||
///
|
||||
/// The SHA384 hash of an X.509 certificate's To-Be-Signed contents.
|
||||
///
|
||||
EFI_SHA384_HASH ToBeSignedHash;
|
||||
///
|
||||
/// The time that the certificate shall be considered to be revoked.
|
||||
///
|
||||
EFI_TIME TimeOfRevocation;
|
||||
} EFI_CERT_X509_SHA384;
|
||||
|
||||
typedef struct {
|
||||
///
|
||||
/// The SHA512 hash of an X.509 certificate's To-Be-Signed contents.
|
||||
///
|
||||
EFI_SHA512_HASH ToBeSignedHash;
|
||||
///
|
||||
/// The time that the certificate shall be considered to be revoked.
|
||||
///
|
||||
EFI_TIME TimeOfRevocation;
|
||||
} EFI_CERT_X509_SHA512;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
///
|
||||
@ -184,6 +223,45 @@ typedef struct {
|
||||
0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a} \
|
||||
}
|
||||
|
||||
///
|
||||
/// This identifies a signature containing the SHA256 hash of an X.509 certificate's
|
||||
/// To-Be-Signed contents, and a time of revocation. The SignatureHeader size shall
|
||||
/// always be 0. The SignatureSize shall always be 16 (size of the SignatureOwner component)
|
||||
/// + 48 bytes for an EFI_CERT_X509_SHA256 structure. If the TimeOfRevocation is non-zero,
|
||||
/// the certificate should be considered to be revoked from that time and onwards, and
|
||||
/// otherwise the certificate shall be considered to always be revoked.
|
||||
///
|
||||
#define EFI_CERT_X509_SHA256_GUID \
|
||||
{ \
|
||||
0x3bd2a492, 0x96c0, 0x4079, {0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed } \
|
||||
}
|
||||
|
||||
///
|
||||
/// This identifies a signature containing the SHA384 hash of an X.509 certificate's
|
||||
/// To-Be-Signed contents, and a time of revocation. The SignatureHeader size shall
|
||||
/// always be 0. The SignatureSize shall always be 16 (size of the SignatureOwner component)
|
||||
/// + 64 bytes for an EFI_CERT_X509_SHA384 structure. If the TimeOfRevocation is non-zero,
|
||||
/// the certificate should be considered to be revoked from that time and onwards, and
|
||||
/// otherwise the certificate shall be considered to always be revoked.
|
||||
///
|
||||
#define EFI_CERT_X509_SHA384_GUID \
|
||||
{ \
|
||||
0x7076876e, 0x80c2, 0x4ee6, {0xaa, 0xd2, 0x28, 0xb3, 0x49, 0xa6, 0x86, 0x5b } \
|
||||
}
|
||||
|
||||
///
|
||||
/// This identifies a signature containing the SHA512 hash of an X.509 certificate's
|
||||
/// To-Be-Signed contents, and a time of revocation. The SignatureHeader size shall
|
||||
/// always be 0. The SignatureSize shall always be 16 (size of the SignatureOwner component)
|
||||
/// + 80 bytes for an EFI_CERT_X509_SHA512 structure. If the TimeOfRevocation is non-zero,
|
||||
/// the certificate should be considered to be revoked from that time and onwards, and
|
||||
/// otherwise the certificate shall be considered to always be revoked.
|
||||
///
|
||||
#define EFI_CERT_X509_SHA512_GUID \
|
||||
{ \
|
||||
0x446dbf63, 0x2502, 0x4cda, {0xbc, 0xfa, 0x24, 0x65, 0xd2, 0xb0, 0xfe, 0x9d } \
|
||||
}
|
||||
|
||||
///
|
||||
/// This identifies a signature containing a DER-encoded PKCS #7 version 1.5 [RFC2315]
|
||||
/// SignedData value.
|
||||
@ -266,6 +344,9 @@ extern EFI_GUID gEfiCertX509Guid;
|
||||
extern EFI_GUID gEfiCertSha224Guid;
|
||||
extern EFI_GUID gEfiCertSha384Guid;
|
||||
extern EFI_GUID gEfiCertSha512Guid;
|
||||
extern EFI_GUID gEfiCertX509Sha256Guid;
|
||||
extern EFI_GUID gEfiCertX509Sha384Guid;
|
||||
extern EFI_GUID gEfiCertX509Sha512Guid;
|
||||
extern EFI_GUID gEfiCertPkcs7Guid;
|
||||
|
||||
#endif
|
@ -523,6 +523,11 @@
|
||||
## Include/Guid/FmpCapsule.h
|
||||
gEfiFmpCapsuleGuid = { 0x6dcbd5ed, 0xe82d, 0x4c44, {0xbd, 0xa1, 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a }}
|
||||
|
||||
## Include/Guid/ImageAuthentication.h
|
||||
gEfiCertX509Sha256Guid = { 0x3bd2a492, 0x96c0, 0x4079, {0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed }}
|
||||
gEfiCertX509Sha384Guid = { 0x7076876e, 0x80c2, 0x4ee6, {0xaa, 0xd2, 0x28, 0xb3, 0x49, 0xa6, 0x86, 0x5b }}
|
||||
gEfiCertX509Sha512Guid = { 0x446dbf63, 0x2502, 0x4cda, {0xbc, 0xfa, 0x24, 0x65, 0xd2, 0xb0, 0xfe, 0x9d }}
|
||||
|
||||
## Include/Protocol/Rng.h
|
||||
gEfiRngAlgorithmSp80090Hash256Guid = { 0xa7af67cb, 0x603b, 0x4d42, {0xba, 0x21, 0x70, 0xbf, 0xb6, 0x29, 0x3f, 0x96 }}
|
||||
gEfiRngAlgorithmSp80090Hmac256Guid = { 0xc5149b43, 0xae85, 0x4f53, {0x99, 0x82, 0xb9, 0x43, 0x35, 0xd3, 0xa9, 0xe7 }}
|
||||
|
@ -66,9 +66,9 @@ UINT8 mHashOidValue[] = {
|
||||
HASH_TABLE mHash[] = {
|
||||
{ L"SHA1", 20, &mHashOidValue[0], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
|
||||
{ L"SHA224", 28, &mHashOidValue[5], 9, NULL, NULL, NULL, NULL },
|
||||
{ L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize,Sha256Init, Sha256Update, Sha256Final},
|
||||
{ L"SHA384", 48, &mHashOidValue[23], 9, NULL, NULL, NULL, NULL },
|
||||
{ L"SHA512", 64, &mHashOidValue[32], 9, NULL, NULL, NULL, NULL }
|
||||
{ L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},
|
||||
{ L"SHA384", 48, &mHashOidValue[23], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},
|
||||
{ L"SHA512", 64, &mHashOidValue[32], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -306,7 +306,7 @@ HashPeImage (
|
||||
SectionHeader = NULL;
|
||||
Status = FALSE;
|
||||
|
||||
if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {
|
||||
if ((HashAlg >= HASHALG_MAX)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -315,13 +315,28 @@ HashPeImage (
|
||||
//
|
||||
ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
|
||||
|
||||
if (HashAlg == HASHALG_SHA1) {
|
||||
switch (HashAlg) {
|
||||
case HASHALG_SHA1:
|
||||
mImageDigestSize = SHA1_DIGEST_SIZE;
|
||||
mCertType = gEfiCertSha1Guid;
|
||||
} else if (HashAlg == HASHALG_SHA256) {
|
||||
break;
|
||||
|
||||
case HASHALG_SHA256:
|
||||
mImageDigestSize = SHA256_DIGEST_SIZE;
|
||||
mCertType = gEfiCertSha256Guid;
|
||||
} else {
|
||||
break;
|
||||
|
||||
case HASHALG_SHA384:
|
||||
mImageDigestSize = SHA384_DIGEST_SIZE;
|
||||
mCertType = gEfiCertSha384Guid;
|
||||
break;
|
||||
|
||||
case HASHALG_SHA512:
|
||||
mImageDigestSize = SHA512_DIGEST_SIZE;
|
||||
mCertType = gEfiCertSha512Guid;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -803,6 +818,124 @@ AddImageExeInfo (
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the hash of an given X.509 certificate is in forbidden database (DBX).
|
||||
|
||||
@param[in] Certificate Pointer to X.509 Certificate that is searched for.
|
||||
@param[in] CertSize Size of X.509 Certificate.
|
||||
@param[in] SignatureList Pointer to the Signature List in forbidden database.
|
||||
@param[in] SignatureListSize Size of Signature List.
|
||||
@param[out] RevocationTime Return the time that the certificate was revoked.
|
||||
|
||||
@return TRUE The certificate hash is found in the forbidden database.
|
||||
@return FALSE The certificate hash is not found in the forbidden database.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsCertHashFoundInDatabase (
|
||||
IN UINT8 *Certificate,
|
||||
IN UINTN CertSize,
|
||||
IN EFI_SIGNATURE_LIST *SignatureList,
|
||||
IN UINTN SignatureListSize,
|
||||
OUT EFI_TIME *RevocationTime
|
||||
)
|
||||
{
|
||||
BOOLEAN IsFound;
|
||||
EFI_STATUS Status;
|
||||
EFI_SIGNATURE_LIST *DbxList;
|
||||
UINTN DbxSize;
|
||||
EFI_SIGNATURE_DATA *CertHash;
|
||||
UINTN CertHashCount;
|
||||
UINTN Index;
|
||||
UINT32 HashAlg;
|
||||
VOID *HashCtx;
|
||||
UINT8 CertDigest[MAX_DIGEST_SIZE];
|
||||
UINT8 *DbxCertHash;
|
||||
UINTN SiglistHeaderSize;
|
||||
|
||||
IsFound = FALSE;
|
||||
DbxList = SignatureList;
|
||||
DbxSize = SignatureListSize;
|
||||
HashCtx = NULL;
|
||||
HashAlg = HASHALG_MAX;
|
||||
|
||||
ASSERT (RevocationTime != NULL);
|
||||
|
||||
while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {
|
||||
//
|
||||
// Determine Hash Algorithm of Certificate in the forbidden database.
|
||||
//
|
||||
if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {
|
||||
HashAlg = HASHALG_SHA256;
|
||||
} else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {
|
||||
HashAlg = HASHALG_SHA384;
|
||||
} else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {
|
||||
HashAlg = HASHALG_SHA512;
|
||||
} else {
|
||||
DbxSize -= DbxList->SignatureListSize;
|
||||
DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the hash value of current db certificate for comparision.
|
||||
//
|
||||
if (mHash[HashAlg].GetContextSize == NULL) {
|
||||
goto Done;
|
||||
}
|
||||
ZeroMem (CertDigest, MAX_DIGEST_SIZE);
|
||||
HashCtx = AllocatePool (mHash[HashAlg].GetContextSize ());
|
||||
if (HashCtx == NULL) {
|
||||
goto Done;
|
||||
}
|
||||
Status = mHash[HashAlg].HashInit (HashCtx);
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
Status = mHash[HashAlg].HashUpdate (HashCtx, Certificate, CertSize);
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
Status = mHash[HashAlg].HashFinal (HashCtx, CertDigest);
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;
|
||||
CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);
|
||||
CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;
|
||||
for (Index = 0; Index < CertHashCount; Index++) {
|
||||
//
|
||||
// Iterate each Signature Data Node within this CertList for verify.
|
||||
//
|
||||
DbxCertHash = CertHash->SignatureData;
|
||||
if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {
|
||||
//
|
||||
// Hash of Certificate is found in forbidden database.
|
||||
//
|
||||
IsFound = TRUE;
|
||||
|
||||
//
|
||||
// Return the revocation time.
|
||||
//
|
||||
CopyMem (RevocationTime, (EFI_TIME *)(DbxCertHash + mHash[HashAlg].DigestLength), sizeof (EFI_TIME));
|
||||
goto Done;
|
||||
}
|
||||
CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);
|
||||
}
|
||||
|
||||
DbxSize -= DbxList->SignatureListSize;
|
||||
DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
|
||||
}
|
||||
|
||||
Done:
|
||||
if (HashCtx != NULL) {
|
||||
FreePool (HashCtx);
|
||||
}
|
||||
|
||||
return IsFound;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether signature is in specified database.
|
||||
|
||||
@ -831,6 +964,7 @@ IsSignatureFoundInDatabase (
|
||||
UINTN Index;
|
||||
UINTN CertCount;
|
||||
BOOLEAN IsFound;
|
||||
|
||||
//
|
||||
// Read signature database variable.
|
||||
//
|
||||
@ -890,24 +1024,296 @@ Done:
|
||||
}
|
||||
|
||||
/**
|
||||
Verify PKCS#7 SignedData using certificate found in Variable which formatted
|
||||
as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
|
||||
Check whether the timestamp is valid by comparing the signing time and the revocation time.
|
||||
|
||||
@param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.
|
||||
@param[in] AuthDataSize Size of the Authenticode Signature in bytes.
|
||||
@param[in] VariableName Name of Variable to search for Certificate.
|
||||
@param[in] VendorGuid Variable vendor GUID.
|
||||
@param SigningTime A pointer to the signing time.
|
||||
@param RevocationTime A pointer to the revocation time.
|
||||
|
||||
@retval TRUE Image pass verification.
|
||||
@retval FALSE Image fail verification.
|
||||
@retval TRUE The SigningTime is not later than the RevocationTime.
|
||||
@retval FALSE The SigningTime is later than the RevocationTime.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsPkcsSignedDataVerifiedBySignatureList (
|
||||
IsValidSignatureByTimestamp (
|
||||
IN EFI_TIME *SigningTime,
|
||||
IN EFI_TIME *RevocationTime
|
||||
)
|
||||
{
|
||||
if (SigningTime->Year != RevocationTime->Year) {
|
||||
return (BOOLEAN) (SigningTime->Year < RevocationTime->Year);
|
||||
} else if (SigningTime->Month != RevocationTime->Month) {
|
||||
return (BOOLEAN) (SigningTime->Month < RevocationTime->Month);
|
||||
} else if (SigningTime->Day != RevocationTime->Day) {
|
||||
return (BOOLEAN) (SigningTime->Day < RevocationTime->Day);
|
||||
} else if (SigningTime->Hour != RevocationTime->Hour) {
|
||||
return (BOOLEAN) (SigningTime->Hour < RevocationTime->Hour);
|
||||
} else if (SigningTime->Minute != RevocationTime->Minute) {
|
||||
return (BOOLEAN) (SigningTime->Minute < RevocationTime->Minute);
|
||||
}
|
||||
|
||||
return (BOOLEAN) (SigningTime->Second <= RevocationTime->Second);
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the given time value is zero.
|
||||
|
||||
@param[in] Time Pointer of a time value.
|
||||
|
||||
@retval TRUE The Time is Zero.
|
||||
@retval FALSE The Time is not Zero.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsTimeZero (
|
||||
IN EFI_TIME *Time
|
||||
)
|
||||
{
|
||||
if ((Time->Year == 0) && (Time->Month == 0) && (Time->Day == 0) &&
|
||||
(Time->Hour == 0) && (Time->Minute == 0) && (Time->Second == 0)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the timestamp signature is valid and the signing time is also earlier than
|
||||
the revocation time.
|
||||
|
||||
@param[in] AuthData Pointer to the Authenticode signature retrieved from signed image.
|
||||
@param[in] AuthDataSize Size of the Authenticode signature in bytes.
|
||||
@param[in] RevocationTime The time that the certificate was revoked.
|
||||
|
||||
@retval TRUE Timestamp signature is valid and signing time is no later than the
|
||||
revocation time.
|
||||
@retval FALSE Timestamp signature is not valid or the signing time is later than the
|
||||
revocation time.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PassTimestampCheck (
|
||||
IN UINT8 *AuthData,
|
||||
IN UINTN AuthDataSize,
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid
|
||||
IN EFI_TIME *RevocationTime
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN VerifyStatus;
|
||||
EFI_SIGNATURE_LIST *CertList;
|
||||
EFI_SIGNATURE_DATA *Cert;
|
||||
UINT8 *DbtData;
|
||||
UINTN DbtDataSize;
|
||||
UINT8 *RootCert;
|
||||
UINTN RootCertSize;
|
||||
UINTN Index;
|
||||
UINTN CertCount;
|
||||
EFI_TIME SigningTime;
|
||||
|
||||
//
|
||||
// Variable Initialization
|
||||
//
|
||||
VerifyStatus = FALSE;
|
||||
DbtData = NULL;
|
||||
CertList = NULL;
|
||||
Cert = NULL;
|
||||
RootCert = NULL;
|
||||
RootCertSize = 0;
|
||||
|
||||
//
|
||||
// If RevocationTime is zero, the certificate shall be considered to always be revoked.
|
||||
//
|
||||
if (IsTimeZero (RevocationTime)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// RevocationTime is non-zero, the certificate should be considered to be revoked from that time and onwards.
|
||||
// Using the dbt to get the trusted TSA certificates.
|
||||
//
|
||||
DbtDataSize = 0;
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, NULL);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
DbtData = (UINT8 *) AllocateZeroPool (DbtDataSize);
|
||||
if (DbtData == NULL) {
|
||||
goto Done;
|
||||
}
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, (VOID *) DbtData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
CertList = (EFI_SIGNATURE_LIST *) DbtData;
|
||||
while ((DbtDataSize > 0) && (DbtDataSize >= CertList->SignatureListSize)) {
|
||||
if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
|
||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
||||
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
||||
for (Index = 0; Index < CertCount; Index++) {
|
||||
//
|
||||
// Iterate each Signature Data Node within this CertList for verify.
|
||||
//
|
||||
RootCert = Cert->SignatureData;
|
||||
RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);
|
||||
//
|
||||
// Get the signing time if the timestamp signature is valid.
|
||||
//
|
||||
if (ImageTimestampVerify (AuthData, AuthDataSize, RootCert, RootCertSize, &SigningTime)) {
|
||||
//
|
||||
// The signer signature is valid only when the signing time is earlier than revocation time.
|
||||
//
|
||||
if (IsValidSignatureByTimestamp (&SigningTime, RevocationTime)) {
|
||||
VerifyStatus = TRUE;
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
|
||||
}
|
||||
}
|
||||
DbtDataSize -= CertList->SignatureListSize;
|
||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||
}
|
||||
|
||||
Done:
|
||||
if (DbtData != NULL) {
|
||||
FreePool (DbtData);
|
||||
}
|
||||
|
||||
return VerifyStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the image signature is forbidden by the forbidden database (dbx).
|
||||
The image is forbidden to load if any certificates for signing are revoked before signing time.
|
||||
|
||||
@param[in] AuthData Pointer to the Authenticode signature retrieved from the signed image.
|
||||
@param[in] AuthDataSize Size of the Authenticode signature in bytes.
|
||||
|
||||
@retval TRUE Image is forbidden by dbx.
|
||||
@retval FALSE Image is not forbidden by dbx.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsForbiddenByDbx (
|
||||
IN UINT8 *AuthData,
|
||||
IN UINTN AuthDataSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN IsForbidden;
|
||||
UINT8 *Data;
|
||||
UINTN DataSize;
|
||||
UINTN Index;
|
||||
UINT8 *CertBuffer;
|
||||
UINTN BufferLength;
|
||||
UINT8 *TrustedCert;
|
||||
UINTN TrustedCertLength;
|
||||
UINT8 CertNumber;
|
||||
UINT8 *CertPtr;
|
||||
UINT8 *Cert;
|
||||
UINTN CertSize;
|
||||
EFI_TIME RevocationTime;
|
||||
|
||||
//
|
||||
// Variable Initialization
|
||||
//
|
||||
IsForbidden = FALSE;
|
||||
Data = NULL;
|
||||
Cert = NULL;
|
||||
CertBuffer = NULL;
|
||||
BufferLength = 0;
|
||||
TrustedCert = NULL;
|
||||
TrustedCertLength = 0;
|
||||
|
||||
//
|
||||
// The image will not be forbidden if dbx can't be got.
|
||||
//
|
||||
DataSize = 0;
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
Data = (UINT8 *) AllocateZeroPool (DataSize);
|
||||
if (Data == NULL) {
|
||||
return IsForbidden;
|
||||
}
|
||||
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);
|
||||
}
|
||||
if (EFI_ERROR (Status)) {
|
||||
return IsForbidden;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the certificate stack from AuthData
|
||||
// The output CertStack format will be:
|
||||
// UINT8 CertNumber;
|
||||
// UINT32 Cert1Length;
|
||||
// UINT8 Cert1[];
|
||||
// UINT32 Cert2Length;
|
||||
// UINT8 Cert2[];
|
||||
// ...
|
||||
// UINT32 CertnLength;
|
||||
// UINT8 Certn[];
|
||||
//
|
||||
Pkcs7GetSigners (AuthData, AuthDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength);
|
||||
if (BufferLength == 0) {
|
||||
IsForbidden = TRUE;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if any certificates in AuthData is in the forbidden database.
|
||||
//
|
||||
CertNumber = (UINT8) (*CertBuffer);
|
||||
CertPtr = CertBuffer + 1;
|
||||
for (Index = 0; Index < CertNumber; Index++) {
|
||||
CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);
|
||||
Cert = (UINT8 *)CertPtr + sizeof (UINT32);
|
||||
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Cert, &gEfiCertX509Guid, CertSize)) {
|
||||
//
|
||||
// Raw certificate in dbx means the image signed by the certificate is forbidden.
|
||||
//
|
||||
IsForbidden = TRUE;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {
|
||||
//
|
||||
// Check the timestamp signature and signing time to determine if the image can be trusted.
|
||||
//
|
||||
IsForbidden = TRUE;
|
||||
if (PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime)) {
|
||||
IsForbidden = FALSE;
|
||||
}
|
||||
goto Done;
|
||||
}
|
||||
|
||||
CertPtr = CertPtr + sizeof (UINT32) + CertSize;
|
||||
}
|
||||
|
||||
Done:
|
||||
if (Data != NULL) {
|
||||
FreePool (Data);
|
||||
}
|
||||
|
||||
Pkcs7FreeSigners (CertBuffer);
|
||||
Pkcs7FreeSigners (TrustedCert);
|
||||
|
||||
return IsForbidden;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the image signature can be verified by the trusted certificates in DB database.
|
||||
|
||||
@param[in] AuthData Pointer to the Authenticode signature retrieved from signed image.
|
||||
@param[in] AuthDataSize Size of the Authenticode signature in bytes.
|
||||
|
||||
@retval TRUE Image passed verification using certificate in db.
|
||||
@retval FALSE Image didn't pass verification using certificate in db.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsAllowedByDb (
|
||||
IN UINT8 *AuthData,
|
||||
IN UINTN AuthDataSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
@ -929,14 +1335,14 @@ IsPkcsSignedDataVerifiedBySignatureList (
|
||||
VerifyStatus = FALSE;
|
||||
|
||||
DataSize = 0;
|
||||
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
Data = (UINT8 *) AllocateZeroPool (DataSize);
|
||||
if (Data == NULL) {
|
||||
return VerifyStatus;
|
||||
}
|
||||
|
||||
Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, (VOID *) Data);
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
@ -949,6 +1355,7 @@ IsPkcsSignedDataVerifiedBySignatureList (
|
||||
if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
|
||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
||||
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
||||
|
||||
for (Index = 0; Index < CertCount; Index++) {
|
||||
//
|
||||
// Iterate each Signature Data Node within this CertList for verify.
|
||||
@ -968,12 +1375,14 @@ IsPkcsSignedDataVerifiedBySignatureList (
|
||||
mImageDigestSize
|
||||
);
|
||||
if (VerifyStatus) {
|
||||
SecureBootHook (VariableName, VendorGuid, CertList->SignatureSize, Cert);
|
||||
SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
|
||||
}
|
||||
}
|
||||
|
||||
DataSize -= CertList->SignatureListSize;
|
||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||
}
|
||||
@ -1302,7 +1711,7 @@ DxeImageVerificationHandler (
|
||||
//
|
||||
// Check the digital signature against the revoked certificate in forbidden database (dbx).
|
||||
//
|
||||
if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {
|
||||
if (IsForbiddenByDbx (AuthData, AuthDataSize)) {
|
||||
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
|
||||
VerifyStatus = EFI_ACCESS_DENIED;
|
||||
break;
|
||||
@ -1312,7 +1721,7 @@ DxeImageVerificationHandler (
|
||||
// Check the digital signature against the valid certificate in allowed database (db).
|
||||
//
|
||||
if (EFI_ERROR (VerifyStatus)) {
|
||||
if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
|
||||
if (IsAllowedByDb (AuthData, AuthDataSize)) {
|
||||
VerifyStatus = EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
The internal header file includes the common header files, defines
|
||||
internal structure and functions used by ImageVerificationLib.
|
||||
|
||||
Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
@ -76,9 +76,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#define HASHALG_MAX 0x00000005
|
||||
|
||||
//
|
||||
// Set max digest size as SHA256 Output (32 bytes) by far
|
||||
// Set max digest size as SHA512 Output (64 bytes) by far
|
||||
//
|
||||
#define MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
|
||||
#define MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
|
||||
//
|
||||
//
|
||||
// PKCS7 Certificate definition
|
||||
|
@ -67,6 +67,7 @@
|
||||
[Guids]
|
||||
## SOMETIMES_CONSUMES ## Variable:L"DB"
|
||||
## SOMETIMES_CONSUMES ## Variable:L"DBX"
|
||||
## SOMETIMES_CONSUMES ## Variable:L"DBT"
|
||||
## PRODUCES ## SystemTable
|
||||
## CONSUMES ## SystemTable
|
||||
gEfiImageSecurityDatabaseGuid
|
||||
@ -79,11 +80,21 @@
|
||||
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertSha256Guid
|
||||
|
||||
## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
|
||||
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertSha384Guid
|
||||
|
||||
## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
|
||||
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertSha512Guid
|
||||
|
||||
gEfiCertX509Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertX509Sha256Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertX509Sha384Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertX509Sha512Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
|
||||
gEfiCertPkcs7Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the certificate.
|
||||
|
||||
[Pcd]
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy ## SOMETIMES_CONSUMES
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy ## SOMETIMES_CONSUMES
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy ## SOMETIMES_CONSUMES
|
||||
|
@ -77,7 +77,10 @@ EFI_SIGNATURE_ITEM mSupportSigItem[] = {
|
||||
{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 }
|
||||
{EFI_CERT_SHA512_GUID, 0, 64 },
|
||||
{EFI_CERT_X509_SHA256_GUID, 0, 48 },
|
||||
{EFI_CERT_X509_SHA384_GUID, 0, 64 },
|
||||
{EFI_CERT_X509_SHA512_GUID, 0, 80 }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -885,7 +888,7 @@ UpdatePlatformMode (
|
||||
}
|
||||
|
||||
/**
|
||||
Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK/db/dbx variable.
|
||||
Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK/db/dbx/dbt variable.
|
||||
|
||||
@param[in] VariableName Name of Variable to be check.
|
||||
@param[in] VendorGuid Variable vendor GUID.
|
||||
@ -921,9 +924,10 @@ CheckSignatureListFormat(
|
||||
|
||||
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) ||
|
||||
} else if ((CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) ||
|
||||
(CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
|
||||
(StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0 || StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))){
|
||||
((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) ||
|
||||
(StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0)))) {
|
||||
IsPk = FALSE;
|
||||
} else {
|
||||
return EFI_SUCCESS;
|
||||
@ -1096,7 +1100,7 @@ ProcessVarWithPk (
|
||||
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 ||
|
||||
(Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {
|
||||
//
|
||||
// PK, KEK and db/dbx should set EFI_VARIABLE_NON_VOLATILE attribute and should be a time-based
|
||||
// PK, KEK and db/dbx/dbt should set EFI_VARIABLE_NON_VOLATILE attribute and should be a time-based
|
||||
// authenticated variable.
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
@ -1221,7 +1225,7 @@ ProcessVarWithKek (
|
||||
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 and should be a time-based
|
||||
// DB, DBX and DBT should set EFI_VARIABLE_NON_VOLATILE attribute and should be a time-based
|
||||
// authenticated variable.
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
@ -2349,7 +2353,7 @@ VerifyTimeBasedPayload (
|
||||
} else if (AuthVarType == AuthVarTypePriv) {
|
||||
|
||||
//
|
||||
// Process common authenticated variable except PK/KEK/DB/DBX.
|
||||
// Process common authenticated variable except PK/KEK/DB/DBX/DBT.
|
||||
// Get signer's certificates from SignedData.
|
||||
//
|
||||
VerifyStatus = Pkcs7GetSigners (
|
||||
@ -2469,4 +2473,3 @@ Exit:
|
||||
&CertData->TimeStamp
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2108,7 +2108,8 @@ UpdateVariable (
|
||||
MaxDataSize = PcdGet32 (PcdMaxVariableSize) - DataOffset;
|
||||
|
||||
if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
|
||||
((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))) ||
|
||||
((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) ||
|
||||
(StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0))) ||
|
||||
(CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {
|
||||
//
|
||||
// For variables with formatted as EFI_SIGNATURE_LIST, the driver shall not perform an append of
|
||||
@ -3185,7 +3186,8 @@ VariableServiceSetVariable (
|
||||
} else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {
|
||||
Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes, FALSE);
|
||||
} else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
|
||||
((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))) {
|
||||
((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))
|
||||
|| (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2)) == 0) {
|
||||
Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes, FALSE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = ProcessVarWithKek (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);
|
||||
@ -3937,4 +3939,3 @@ GetFvbInfoByAddress (
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
VFR file used by the SecureBoot configuration component.
|
||||
|
||||
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
@ -136,6 +136,14 @@ formset
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_SECURE_BOOT_DBX_OPTION;
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
goto FORMID_SECURE_BOOT_DBT_OPTION_FORM,
|
||||
prompt = STRING_TOKEN(STR_SECURE_BOOT_DBT_OPTION),
|
||||
help = STRING_TOKEN(STR_SECURE_BOOT_DBT_OPTION_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_SECURE_BOOT_DBT_OPTION;
|
||||
|
||||
endform;
|
||||
|
||||
//
|
||||
@ -326,6 +334,29 @@ formset
|
||||
|
||||
endform;
|
||||
|
||||
//
|
||||
// ##9 Form: 'DBT Options'
|
||||
//
|
||||
form formid = FORMID_SECURE_BOOT_DBT_OPTION_FORM,
|
||||
title = STRING_TOKEN(STR_SECURE_BOOT_DBT_OPTION);
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
goto SECUREBOOT_ENROLL_SIGNATURE_TO_DBT,
|
||||
prompt = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE),
|
||||
help = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE),
|
||||
flags = 0;
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
goto SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
|
||||
prompt = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE),
|
||||
help = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE),
|
||||
flags = INTERACTIVE,
|
||||
key = SECUREBOOT_DELETE_SIGNATURE_FROM_DBT;
|
||||
|
||||
endform;
|
||||
|
||||
//
|
||||
// Form: 'Delete Signature' for DB Options.
|
||||
//
|
||||
@ -350,6 +381,18 @@ formset
|
||||
|
||||
endform;
|
||||
|
||||
//
|
||||
// Form: 'Delete Signature' for DBT Options.
|
||||
//
|
||||
form formid = SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
|
||||
title = STRING_TOKEN(STR_SECURE_BOOT_DELETE_SIGNATURE);
|
||||
|
||||
label LABEL_DBT_DELETE;
|
||||
label LABEL_END;
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
endform;
|
||||
|
||||
//
|
||||
// Form: 'Enroll Signature' for DB options.
|
||||
//
|
||||
@ -409,7 +452,6 @@ formset
|
||||
flags = INTERACTIVE,
|
||||
key = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
label SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
|
||||
label LABEL_END;
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
@ -423,6 +465,38 @@ formset
|
||||
maxsize = SECURE_BOOT_GUID_SIZE,
|
||||
endstring;
|
||||
|
||||
oneof name = SignatureFormatInDbx,
|
||||
varid = SECUREBOOT_CONFIGURATION.CertificateFormat,
|
||||
prompt = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_PROMPT),
|
||||
help = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_HELP),
|
||||
option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_SHA256), value = 0x2, flags = DEFAULT;
|
||||
option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_SHA384), value = 0x3, flags = 0;
|
||||
option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_SHA512), value = 0x4, flags = 0;
|
||||
option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_RAW), value = 0x5, flags = 0;
|
||||
endoneof;
|
||||
|
||||
suppressif ideqval SECUREBOOT_CONFIGURATION.CertificateFormat == 5;
|
||||
checkbox varid = SECUREBOOT_CONFIGURATION.AlwaysRevocation,
|
||||
prompt = STRING_TOKEN(STR_ALWAYS_CERTIFICATE_REVOCATION_PROMPT),
|
||||
help = STRING_TOKEN(STR_ALWAYS_CERTIFICATE_REVOCATION_HELP),
|
||||
flags = INTERACTIVE,
|
||||
endcheckbox;
|
||||
|
||||
suppressif ideqval SECUREBOOT_CONFIGURATION.AlwaysRevocation == 1;
|
||||
date varid = SECUREBOOT_CONFIGURATION.RevocationDate,
|
||||
prompt = STRING_TOKEN(STR_CERTIFICATE_REVOCATION_DATE_PROMPT),
|
||||
help = STRING_TOKEN(STR_CERTIFICATE_REVOCATION_DATE_HELP),
|
||||
flags = STORAGE_NORMAL,
|
||||
enddate;
|
||||
|
||||
time varid = SECUREBOOT_CONFIGURATION.RevocationTime,
|
||||
prompt = STRING_TOKEN(STR_CERTIFICATE_REVOCATION_TIME_PROMPT),
|
||||
help = STRING_TOKEN(STR_CERTIFICATE_REVOCATION_TIME_HELP),
|
||||
flags = STORAGE_NORMAL,
|
||||
endtime;
|
||||
endif;
|
||||
endif;
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
@ -440,6 +514,51 @@ formset
|
||||
|
||||
endform;
|
||||
|
||||
//
|
||||
// Form: 'Enroll Signature' for DBT options.
|
||||
//
|
||||
form formid = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT,
|
||||
title = STRING_TOKEN(STR_SECURE_BOOT_ENROLL_SIGNATURE);
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
goto FORM_FILE_EXPLORER_ID_DBT,
|
||||
prompt = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE),
|
||||
help = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE),
|
||||
flags = INTERACTIVE,
|
||||
key = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
label SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;
|
||||
label LABEL_END;
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
string varid = SECUREBOOT_CONFIGURATION.SignatureGuid,
|
||||
prompt = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID),
|
||||
help = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID_HELP),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_SECURE_BOOT_SIGNATURE_GUID_DBT,
|
||||
minsize = SECURE_BOOT_GUID_SIZE,
|
||||
maxsize = SECURE_BOOT_GUID_SIZE,
|
||||
endstring;
|
||||
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
subtitle text = STRING_TOKEN(STR_NULL);
|
||||
|
||||
goto FORMID_SECURE_BOOT_OPTION_FORM,
|
||||
prompt = STRING_TOKEN(STR_SAVE_AND_EXIT),
|
||||
help = STRING_TOKEN(STR_SAVE_AND_EXIT),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_VALUE_SAVE_AND_EXIT_DBT;
|
||||
|
||||
goto FORMID_SECURE_BOOT_OPTION_FORM,
|
||||
prompt = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
|
||||
help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_VALUE_NO_SAVE_AND_EXIT_DBT;
|
||||
|
||||
endform;
|
||||
|
||||
//
|
||||
// File Explorer for PK
|
||||
//
|
||||
@ -480,6 +599,15 @@ formset
|
||||
label LABEL_END;
|
||||
endform;
|
||||
|
||||
//
|
||||
// File Explorer for DBT
|
||||
//
|
||||
form formid = FORM_FILE_EXPLORER_ID_DBT,
|
||||
title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);
|
||||
|
||||
label FORM_FILE_EXPLORER_ID;
|
||||
label LABEL_END;
|
||||
endform;
|
||||
|
||||
//
|
||||
// Enroll Pk from File Commit Form
|
||||
@ -495,12 +623,14 @@ formset
|
||||
text
|
||||
help = STRING_TOKEN(STR_SAVE_AND_EXIT),
|
||||
text = STRING_TOKEN(STR_SAVE_AND_EXIT),
|
||||
text = STRING_TOKEN(STR_NULL),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_VALUE_SAVE_AND_EXIT_PK;
|
||||
|
||||
text
|
||||
help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
|
||||
text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
|
||||
text = STRING_TOKEN(STR_NULL),
|
||||
flags = INTERACTIVE,
|
||||
key = KEY_VALUE_NO_SAVE_AND_EXIT_PK;
|
||||
|
||||
|
@ -105,6 +105,10 @@
|
||||
gEfiFileSystemVolumeLabelInfoIdGuid ## SOMETIMES_CONSUMES ## GUID # Indicate the information type
|
||||
gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID # Indicate the information type
|
||||
|
||||
gEfiCertX509Sha256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the certificate.
|
||||
gEfiCertX509Sha384Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the certificate.
|
||||
gEfiCertX509Sha512Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the certificate.
|
||||
|
||||
[Protocols]
|
||||
gEfiHiiConfigAccessProtocolGuid ## PRODUCES
|
||||
gEfiDevicePathProtocolGuid ## PRODUCES
|
||||
@ -119,4 +123,3 @@
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
SecureBootConfigDxeExtra.uni
|
||||
|
@ -1032,6 +1032,9 @@ UpdateFileExplorePage (
|
||||
} else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDbx) {
|
||||
FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
|
||||
FileFormId = FORM_FILE_EXPLORER_ID_DBX;
|
||||
} else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDbt) {
|
||||
FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;
|
||||
FileFormId = FORM_FILE_EXPLORER_ID_DBT;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@ -1156,6 +1159,8 @@ UpdateFileExplorer (
|
||||
FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;
|
||||
} else if (PrivateData->FeCurrentState == FileExplorerStateEnrollSignatureFileToDbx) {
|
||||
FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
|
||||
} else if (PrivateData->FeCurrentState == FileExplorerStateEnrollSignatureFileToDbt) {
|
||||
FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
@ -1226,4 +1231,3 @@ CleanUpPage (
|
||||
mEndOpCodeHandle // LABEL_END
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -65,9 +65,9 @@ UINT8 mHashOidValue[] = {
|
||||
HASH_TABLE mHash[] = {
|
||||
{ L"SHA1", 20, &mHashOidValue[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
|
||||
{ L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL },
|
||||
{ L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize,Sha256Init, Sha256Update, Sha256Final},
|
||||
{ L"SHA384", 48, &mHashOidValue[31], 9, NULL, NULL, NULL, NULL },
|
||||
{ L"SHA512", 64, &mHashOidValue[40], 9, NULL, NULL, NULL, NULL }
|
||||
{ L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},
|
||||
{ L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},
|
||||
{ L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}
|
||||
};
|
||||
|
||||
//
|
||||
@ -840,7 +840,7 @@ EnrollKeyExchangeKey (
|
||||
}
|
||||
|
||||
/**
|
||||
Enroll a new X509 certificate into Signature Database (DB or DBX) without
|
||||
Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without
|
||||
KEK's authentication.
|
||||
|
||||
@param[in] PrivateData The module's private data.
|
||||
@ -966,6 +966,622 @@ ON_EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether signature is in specified database.
|
||||
|
||||
@param[in] VariableName Name of database variable that is searched in.
|
||||
@param[in] Signature Pointer to signature that is searched for.
|
||||
@param[in] SignatureSize Size of Signature.
|
||||
|
||||
@return TRUE Found the signature in the variable database.
|
||||
@return FALSE Not found the signature in the variable database.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsSignatureFoundInDatabase (
|
||||
IN CHAR16 *VariableName,
|
||||
IN UINT8 *Signature,
|
||||
IN UINTN SignatureSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SIGNATURE_LIST *CertList;
|
||||
EFI_SIGNATURE_DATA *Cert;
|
||||
UINTN DataSize;
|
||||
UINT8 *Data;
|
||||
UINTN Index;
|
||||
UINTN CertCount;
|
||||
BOOLEAN IsFound;
|
||||
|
||||
//
|
||||
// Read signature database variable.
|
||||
//
|
||||
IsFound = FALSE;
|
||||
Data = NULL;
|
||||
DataSize = 0;
|
||||
Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
|
||||
if (Status != EFI_BUFFER_TOO_SMALL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Data = (UINT8 *) AllocateZeroPool (DataSize);
|
||||
if (Data == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Enumerate all signature data in SigDB to check if executable's signature exists.
|
||||
//
|
||||
CertList = (EFI_SIGNATURE_LIST *) Data;
|
||||
while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
|
||||
CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
||||
if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &gEfiCertX509Guid))) {
|
||||
for (Index = 0; Index < CertCount; Index++) {
|
||||
if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {
|
||||
//
|
||||
// Find the signature in database.
|
||||
//
|
||||
IsFound = TRUE;
|
||||
break;
|
||||
}
|
||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
|
||||
}
|
||||
|
||||
if (IsFound) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DataSize -= CertList->SignatureListSize;
|
||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||
}
|
||||
|
||||
Done:
|
||||
if (Data != NULL) {
|
||||
FreePool (Data);
|
||||
}
|
||||
|
||||
return IsFound;
|
||||
}
|
||||
|
||||
/**
|
||||
Calculate the hash of a certificate data with the specified hash algorithm.
|
||||
|
||||
@param[in] CertData The certificate data to be hashed.
|
||||
@param[in] CertSize The certificate size in bytes.
|
||||
@param[in] HashAlg The specified hash algorithm.
|
||||
@param[out] CertHash The output digest of the certificate
|
||||
|
||||
@retval TRUE Successfully got the hash of the CertData.
|
||||
@retval FALSE Failed to get the hash of CertData.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
CalculateCertHash (
|
||||
IN UINT8 *CertData,
|
||||
IN UINTN CertSize,
|
||||
IN UINT32 HashAlg,
|
||||
OUT UINT8 *CertHash
|
||||
)
|
||||
{
|
||||
BOOLEAN Status;
|
||||
VOID *HashCtx;
|
||||
UINTN CtxSize;
|
||||
|
||||
HashCtx = NULL;
|
||||
Status = FALSE;
|
||||
|
||||
if (HashAlg >= HASHALG_MAX) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// 1. Initialize context of hash.
|
||||
//
|
||||
CtxSize = mHash[HashAlg].GetContextSize ();
|
||||
HashCtx = AllocatePool (CtxSize);
|
||||
ASSERT (HashCtx != NULL);
|
||||
|
||||
//
|
||||
// 2. Initialize a hash context.
|
||||
//
|
||||
Status = mHash[HashAlg].HashInit (HashCtx);
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// 3. Calculate the hash.
|
||||
//
|
||||
Status = mHash[HashAlg].HashUpdate (HashCtx, CertData, CertSize);
|
||||
if (!Status) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// 4. Get the hash result.
|
||||
//
|
||||
ZeroMem (CertHash, mHash[HashAlg].DigestLength);
|
||||
Status = mHash[HashAlg].HashFinal (HashCtx, CertHash);
|
||||
|
||||
Done:
|
||||
if (HashCtx != NULL) {
|
||||
FreePool (HashCtx);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the hash of an X.509 certificate is in forbidden database (DBX).
|
||||
|
||||
@param[in] Certificate Pointer to X.509 Certificate that is searched for.
|
||||
@param[in] CertSize Size of X.509 Certificate.
|
||||
|
||||
@return TRUE Found the certificate hash in the forbidden database.
|
||||
@return FALSE Certificate hash is Not found in the forbidden database.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsCertHashFoundInDbx (
|
||||
IN UINT8 *Certificate,
|
||||
IN UINTN CertSize
|
||||
)
|
||||
{
|
||||
BOOLEAN IsFound;
|
||||
EFI_STATUS Status;
|
||||
EFI_SIGNATURE_LIST *DbxList;
|
||||
EFI_SIGNATURE_DATA *CertHash;
|
||||
UINTN CertHashCount;
|
||||
UINTN Index;
|
||||
UINT32 HashAlg;
|
||||
UINT8 CertDigest[MAX_DIGEST_SIZE];
|
||||
UINT8 *DbxCertHash;
|
||||
UINTN SiglistHeaderSize;
|
||||
UINT8 *Data;
|
||||
UINTN DataSize;
|
||||
|
||||
IsFound = FALSE;
|
||||
HashAlg = HASHALG_MAX;
|
||||
Data = NULL;
|
||||
|
||||
//
|
||||
// Read signature database variable.
|
||||
//
|
||||
DataSize = 0;
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
|
||||
if (Status != EFI_BUFFER_TOO_SMALL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Data = (UINT8 *) AllocateZeroPool (DataSize);
|
||||
if (Data == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether the certificate hash exists in the forbidden database.
|
||||
//
|
||||
DbxList = (EFI_SIGNATURE_LIST *) Data;
|
||||
while ((DataSize > 0) && (DataSize >= DbxList->SignatureListSize)) {
|
||||
//
|
||||
// Determine Hash Algorithm of Certificate in the forbidden database.
|
||||
//
|
||||
if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {
|
||||
HashAlg = HASHALG_SHA256;
|
||||
} else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {
|
||||
HashAlg = HASHALG_SHA384;
|
||||
} else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {
|
||||
HashAlg = HASHALG_SHA512;
|
||||
} else {
|
||||
DataSize -= DbxList->SignatureListSize;
|
||||
DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the hash value of current db certificate for comparision.
|
||||
//
|
||||
if (!CalculateCertHash (Certificate, CertSize, HashAlg, CertDigest)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;
|
||||
CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);
|
||||
CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;
|
||||
for (Index = 0; Index < CertHashCount; Index++) {
|
||||
//
|
||||
// Iterate each Signature Data Node within this CertList for verify.
|
||||
//
|
||||
DbxCertHash = CertHash->SignatureData;
|
||||
if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {
|
||||
//
|
||||
// Hash of Certificate is found in forbidden database.
|
||||
//
|
||||
IsFound = TRUE;
|
||||
goto Done;
|
||||
}
|
||||
CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);
|
||||
}
|
||||
|
||||
DataSize -= DbxList->SignatureListSize;
|
||||
DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);
|
||||
}
|
||||
|
||||
Done:
|
||||
if (Data != NULL) {
|
||||
FreePool (Data);
|
||||
}
|
||||
|
||||
return IsFound;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the signature list exists in given variable data.
|
||||
|
||||
It searches the signature list for the ceritificate hash by CertType.
|
||||
If the signature list is found, get the offset of Database for the
|
||||
next hash of a certificate.
|
||||
|
||||
@param[in] Database Variable data to save signature list.
|
||||
@param[in] DatabaseSize Variable size.
|
||||
@param[in] SignatureType The type of the signature.
|
||||
@param[out] Offset The offset to save a new hash of certificate.
|
||||
|
||||
@return TRUE The signature list is found in the forbidden database.
|
||||
@return FALSE The signature list is not found in the forbidden database.
|
||||
**/
|
||||
BOOLEAN
|
||||
GetSignaturelistOffset (
|
||||
IN EFI_SIGNATURE_LIST *Database,
|
||||
IN UINTN DatabaseSize,
|
||||
IN EFI_GUID *SignatureType,
|
||||
OUT UINTN *Offset
|
||||
)
|
||||
{
|
||||
EFI_SIGNATURE_LIST *SigList;
|
||||
UINTN SiglistSize;
|
||||
|
||||
if ((Database == NULL) || (DatabaseSize == 0)) {
|
||||
*Offset = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SigList = Database;
|
||||
SiglistSize = DatabaseSize;
|
||||
while ((SiglistSize > 0) && (SiglistSize >= SigList->SignatureListSize)) {
|
||||
if (CompareGuid (&SigList->SignatureType, SignatureType)) {
|
||||
*Offset = DatabaseSize - SiglistSize;
|
||||
return TRUE;
|
||||
}
|
||||
SiglistSize -= SigList->SignatureListSize;
|
||||
SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);
|
||||
}
|
||||
*Offset = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Enroll a new X509 certificate hash into Signature Database (dbx) without
|
||||
KEK's authentication.
|
||||
|
||||
@param[in] PrivateData The module's private data.
|
||||
@param[in] HashAlg The hash algorithm to enroll the certificate.
|
||||
@param[in] RevocationDate The revocation date of the certificate.
|
||||
@param[in] RevocationTime The revocation time of the certificate.
|
||||
@param[in] AlwaysRevocation Indicate whether the certificate is always revoked.
|
||||
|
||||
@retval EFI_SUCCESS New X509 is enrolled successfully.
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EnrollX509HashtoSigDB (
|
||||
IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
|
||||
IN UINT32 HashAlg,
|
||||
IN EFI_HII_DATE *RevocationDate,
|
||||
IN EFI_HII_TIME *RevocationTime,
|
||||
IN BOOLEAN AlwaysRevocation
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN X509DataSize;
|
||||
VOID *X509Data;
|
||||
EFI_SIGNATURE_LIST *SignatureList;
|
||||
UINTN SignatureListSize;
|
||||
UINT8 *Data;
|
||||
UINT8 *NewData;
|
||||
UINTN DataSize;
|
||||
UINTN DbSize;
|
||||
UINT32 Attr;
|
||||
EFI_SIGNATURE_DATA *SignatureData;
|
||||
UINTN SignatureSize;
|
||||
EFI_GUID SignatureType;
|
||||
UINTN Offset;
|
||||
UINT8 CertHash[MAX_DIGEST_SIZE];
|
||||
UINT16* FilePostFix;
|
||||
UINTN NameLength;
|
||||
EFI_TIME *Time;
|
||||
|
||||
X509DataSize = 0;
|
||||
DbSize = 0;
|
||||
X509Data = NULL;
|
||||
SignatureData = NULL;
|
||||
SignatureList = NULL;
|
||||
Data = NULL;
|
||||
NewData = NULL;
|
||||
|
||||
if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the file's postfix.
|
||||
//
|
||||
NameLength = StrLen (Private->FileContext->FileName);
|
||||
if (NameLength <= 4) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
FilePostFix = Private->FileContext->FileName + NameLength - 4;
|
||||
if (!IsDerEncodeCertificate(FilePostFix)) {
|
||||
//
|
||||
// Only supports DER-encoded X509 certificate.
|
||||
//
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the certificate from file and calculate its hash.
|
||||
//
|
||||
Status = ReadFileContent (
|
||||
Private->FileContext->FHandle,
|
||||
&X509Data,
|
||||
&X509DataSize,
|
||||
0
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
ASSERT (X509Data != NULL);
|
||||
|
||||
if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the variable for enrollment.
|
||||
//
|
||||
DataSize = 0;
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
Data = (UINT8 *) AllocateZeroPool (DataSize);
|
||||
if (Data == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate memory for Signature and fill the Signature
|
||||
//
|
||||
SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + sizeof (EFI_TIME) + mHash[HashAlg].DigestLength;
|
||||
SignatureData = (EFI_SIGNATURE_DATA *) AllocateZeroPool (SignatureSize);
|
||||
if (SignatureData == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
CopyGuid (&SignatureData->SignatureOwner, Private->SignatureGUID);
|
||||
CopyMem (SignatureData->SignatureData, CertHash, mHash[HashAlg].DigestLength);
|
||||
|
||||
//
|
||||
// Fill the time.
|
||||
//
|
||||
if (!AlwaysRevocation) {
|
||||
Time = (EFI_TIME *)(&SignatureData->SignatureData + mHash[HashAlg].DigestLength);
|
||||
Time->Year = RevocationDate->Year;
|
||||
Time->Month = RevocationDate->Month;
|
||||
Time->Day = RevocationDate->Day;
|
||||
Time->Hour = RevocationTime->Hour;
|
||||
Time->Minute = RevocationTime->Minute;
|
||||
Time->Second = RevocationTime->Second;
|
||||
}
|
||||
|
||||
//
|
||||
// Determine the GUID for certificate hash.
|
||||
//
|
||||
switch (HashAlg) {
|
||||
case HASHALG_SHA256:
|
||||
SignatureType = gEfiCertX509Sha256Guid;
|
||||
break;
|
||||
case HASHALG_SHA384:
|
||||
SignatureType = gEfiCertX509Sha384Guid;
|
||||
break;
|
||||
case HASHALG_SHA512:
|
||||
SignatureType = gEfiCertX509Sha512Guid;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Add signature into the new variable data buffer
|
||||
//
|
||||
if (GetSignaturelistOffset((EFI_SIGNATURE_LIST *)Data, DataSize, &SignatureType, &Offset)) {
|
||||
//
|
||||
// Add the signature to the found signaturelist.
|
||||
//
|
||||
DbSize = DataSize + SignatureSize;
|
||||
NewData = AllocateZeroPool (DbSize);
|
||||
if (NewData == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
SignatureList = (EFI_SIGNATURE_LIST *)(Data + Offset);
|
||||
SignatureListSize = (UINTN) ReadUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize);
|
||||
CopyMem (NewData, Data, Offset + SignatureListSize);
|
||||
|
||||
SignatureList = (EFI_SIGNATURE_LIST *)(NewData + Offset);
|
||||
WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32)(SignatureListSize + SignatureSize));
|
||||
|
||||
Offset += SignatureListSize;
|
||||
CopyMem (NewData + Offset, SignatureData, SignatureSize);
|
||||
CopyMem (NewData + Offset + SignatureSize, Data + Offset, DataSize - Offset);
|
||||
|
||||
FreePool (Data);
|
||||
Data = NewData;
|
||||
DataSize = DbSize;
|
||||
} else {
|
||||
//
|
||||
// Create a new signaturelist, and add the signature into the signaturelist.
|
||||
//
|
||||
DbSize = DataSize + sizeof(EFI_SIGNATURE_LIST) + SignatureSize;
|
||||
NewData = AllocateZeroPool (DbSize);
|
||||
if (NewData == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Fill Certificate Database parameters.
|
||||
//
|
||||
SignatureList = (EFI_SIGNATURE_LIST*) (NewData + DataSize);
|
||||
SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + SignatureSize;
|
||||
WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32) SignatureListSize);
|
||||
WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureSize, (UINT32) SignatureSize);
|
||||
CopyGuid (&SignatureList->SignatureType, &SignatureType);
|
||||
CopyMem ((UINT8* ) SignatureList + sizeof (EFI_SIGNATURE_LIST), SignatureData, SignatureSize);
|
||||
if ((DataSize != 0) && (Data != NULL)) {
|
||||
CopyMem (NewData, Data, DataSize);
|
||||
FreePool (Data);
|
||||
}
|
||||
Data = NewData;
|
||||
DataSize = DbSize;
|
||||
}
|
||||
|
||||
Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &Data);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
|
||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
|
||||
Status = gRT->SetVariable(
|
||||
EFI_IMAGE_SECURITY_DATABASE1,
|
||||
&gEfiImageSecurityDatabaseGuid,
|
||||
Attr,
|
||||
DataSize,
|
||||
Data
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
CloseFile (Private->FileContext->FHandle);
|
||||
Private->FileContext->FileName = NULL;
|
||||
Private->FileContext->FHandle = NULL;
|
||||
|
||||
if (Private->SignatureGUID != NULL) {
|
||||
FreePool (Private->SignatureGUID);
|
||||
Private->SignatureGUID = NULL;
|
||||
}
|
||||
|
||||
if (Data != NULL) {
|
||||
FreePool (Data);
|
||||
}
|
||||
|
||||
if (SignatureData != NULL) {
|
||||
FreePool (SignatureData);
|
||||
}
|
||||
|
||||
if (X509Data != NULL) {
|
||||
FreePool (X509Data);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether a certificate from a file exists in dbx.
|
||||
|
||||
@param[in] PrivateData The module's private data.
|
||||
@param[in] VariableName Variable name of signature database, must be
|
||||
EFI_IMAGE_SECURITY_DATABASE1.
|
||||
|
||||
@retval TRUE The X509 certificate is found in dbx successfully.
|
||||
@retval FALSE The X509 certificate is not found in dbx.
|
||||
**/
|
||||
BOOLEAN
|
||||
IsX509CertInDbx (
|
||||
IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,
|
||||
IN CHAR16 *VariableName
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN X509DataSize;
|
||||
VOID *X509Data;
|
||||
BOOLEAN IsFound;
|
||||
|
||||
//
|
||||
// Read the certificate from file
|
||||
//
|
||||
X509DataSize = 0;
|
||||
X509Data = NULL;
|
||||
Status = ReadFileContent (
|
||||
Private->FileContext->FHandle,
|
||||
&X509Data,
|
||||
&X509DataSize,
|
||||
0
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Check the raw certificate.
|
||||
//
|
||||
IsFound = FALSE;
|
||||
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, X509Data, X509DataSize)) {
|
||||
IsFound = TRUE;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Check the hash of certificate.
|
||||
//
|
||||
if (IsCertHashFoundInDbx (X509Data, X509DataSize)) {
|
||||
IsFound = TRUE;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
if (X509Data != NULL) {
|
||||
FreePool (X509Data);
|
||||
}
|
||||
|
||||
return IsFound;
|
||||
}
|
||||
|
||||
/**
|
||||
Load PE/COFF image information into internal buffer and check its validity.
|
||||
|
||||
@ -1362,7 +1978,8 @@ HashPeImageByType (
|
||||
|
||||
@param[in] PrivateData The module's private data.
|
||||
@param[in] VariableName Variable name of signature database, must be
|
||||
EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
|
||||
EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1
|
||||
or EFI_IMAGE_SECURITY_DATABASE2.
|
||||
|
||||
@retval EFI_SUCCESS New signature is enrolled successfully.
|
||||
@retval EFI_INVALID_PARAMETER The parameter is invalid.
|
||||
@ -1388,6 +2005,10 @@ EnrollImageSignatureToSigDB (
|
||||
Data = NULL;
|
||||
GuidCertData = NULL;
|
||||
|
||||
if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Form the SigDB certificate list.
|
||||
// Format the data item into EFI_SIGNATURE_LIST type.
|
||||
@ -1543,7 +2164,7 @@ ON_EXIT:
|
||||
}
|
||||
|
||||
/**
|
||||
Enroll signature into DB/DBX without KEK's authentication.
|
||||
Enroll signature into DB/DBX/DBT without KEK's authentication.
|
||||
The SignatureOwner GUID will be Private->SignatureGUID.
|
||||
|
||||
@param[in] PrivateData The module's private data.
|
||||
@ -1569,7 +2190,7 @@ EnrollSignatureDatabase (
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);
|
||||
Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
@ -1582,7 +2203,7 @@ EnrollSignatureDatabase (
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
FilePostFix = Private->FileContext->FileName + NameLength - 4;
|
||||
if (IsDerEncodeCertificate(FilePostFix)) {
|
||||
if (IsDerEncodeCertificate (FilePostFix)) {
|
||||
//
|
||||
// Supports DER-encoded X509 certificate.
|
||||
//
|
||||
@ -1593,7 +2214,7 @@ EnrollSignatureDatabase (
|
||||
}
|
||||
|
||||
/**
|
||||
List all signatures in specified signature database (e.g. KEK/DB/DBX)
|
||||
List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)
|
||||
by GUID in the page for user to select and delete as needed.
|
||||
|
||||
@param[in] PrivateData Module's private data.
|
||||
@ -1720,6 +2341,12 @@ UpdateDeletePage (
|
||||
Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);
|
||||
} else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {
|
||||
Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);
|
||||
} else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) {
|
||||
Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID);
|
||||
} else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) {
|
||||
Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID);
|
||||
} else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) {
|
||||
Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID);
|
||||
} else {
|
||||
//
|
||||
// The signature type is not supported in current implementation.
|
||||
@ -2062,7 +2689,10 @@ DeleteSignature (
|
||||
if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||
|
||||
CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||
|
||||
CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||
|
||||
CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)
|
||||
CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) ||
|
||||
CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) ||
|
||||
CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) ||
|
||||
CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)
|
||||
) {
|
||||
//
|
||||
// Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
|
||||
@ -2181,11 +2811,25 @@ SecureBootExtractConfigFromVariable (
|
||||
UINT8 *SecureBootEnable;
|
||||
UINT8 *SetupMode;
|
||||
UINT8 *SecureBootMode;
|
||||
EFI_TIME CurrTime;
|
||||
|
||||
SecureBootEnable = NULL;
|
||||
SetupMode = NULL;
|
||||
SecureBootMode = NULL;
|
||||
|
||||
//
|
||||
// Initilize the Date and Time using system time.
|
||||
//
|
||||
ConfigData->CertificateFormat = HASHALG_RAW;
|
||||
ConfigData->AlwaysRevocation = TRUE;
|
||||
gRT->GetTime (&CurrTime, NULL);
|
||||
ConfigData->RevocationDate.Year = CurrTime.Year;
|
||||
ConfigData->RevocationDate.Month = CurrTime.Month;
|
||||
ConfigData->RevocationDate.Day = CurrTime.Day;
|
||||
ConfigData->RevocationTime.Hour = CurrTime.Hour;
|
||||
ConfigData->RevocationTime.Minute = CurrTime.Minute;
|
||||
ConfigData->RevocationTime.Second = 0;
|
||||
|
||||
//
|
||||
// If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
|
||||
// Checkbox.
|
||||
@ -2573,6 +3217,7 @@ SecureBootCallback (
|
||||
case KEY_SECURE_BOOT_KEK_OPTION:
|
||||
case KEY_SECURE_BOOT_DB_OPTION:
|
||||
case KEY_SECURE_BOOT_DBX_OPTION:
|
||||
case KEY_SECURE_BOOT_DBT_OPTION:
|
||||
//
|
||||
// Clear Signature GUID.
|
||||
//
|
||||
@ -2588,6 +3233,8 @@ SecureBootCallback (
|
||||
LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;
|
||||
} else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {
|
||||
LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
|
||||
} else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) {
|
||||
LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;
|
||||
} else {
|
||||
LabelId = FORMID_ENROLL_KEK_FORM;
|
||||
}
|
||||
@ -2602,14 +3249,18 @@ SecureBootCallback (
|
||||
case FORMID_ENROLL_KEK_FORM:
|
||||
case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:
|
||||
case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:
|
||||
case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT:
|
||||
if (QuestionId == SECUREBOOT_ADD_PK_FILE_FORM_ID) {
|
||||
Private->FeCurrentState = FileExplorerStateEnrollPkFile;
|
||||
} else if (QuestionId == FORMID_ENROLL_KEK_FORM) {
|
||||
Private->FeCurrentState = FileExplorerStateEnrollKekFile;
|
||||
} else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DB) {
|
||||
Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDb;
|
||||
} else {
|
||||
} else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DBX) {
|
||||
Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx;
|
||||
IfrNvData->CertificateFormat = HASHALG_SHA256;
|
||||
} else {
|
||||
Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbt;
|
||||
}
|
||||
|
||||
Private->FeDisplayContext = FileExplorerDisplayUnknown;
|
||||
@ -2674,6 +3325,18 @@ SecureBootCallback (
|
||||
|
||||
break;
|
||||
|
||||
case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT:
|
||||
UpdateDeletePage (
|
||||
Private,
|
||||
EFI_IMAGE_SECURITY_DATABASE2,
|
||||
&gEfiImageSecurityDatabaseGuid,
|
||||
LABEL_DBT_DELETE,
|
||||
SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
|
||||
OPTION_DEL_DBT_QUESTION_ID
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case KEY_VALUE_SAVE_AND_EXIT_KEK:
|
||||
Status = EnrollKeyExchangeKey (Private);
|
||||
if (EFI_ERROR (Status)) {
|
||||
@ -2701,7 +3364,27 @@ SecureBootCallback (
|
||||
break;
|
||||
|
||||
case KEY_VALUE_SAVE_AND_EXIT_DBX:
|
||||
if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) {
|
||||
CreatePopUp (
|
||||
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
||||
&Key,
|
||||
L"Enrollment failed! Same certificate had already been in the dbx!",
|
||||
NULL
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) {
|
||||
Status = EnrollX509HashtoSigDB (
|
||||
Private,
|
||||
IfrNvData->CertificateFormat,
|
||||
&IfrNvData->RevocationDate,
|
||||
&IfrNvData->RevocationTime,
|
||||
IfrNvData->AlwaysRevocation
|
||||
);
|
||||
} else {
|
||||
Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);
|
||||
}
|
||||
if (EFI_ERROR (Status)) {
|
||||
CreatePopUp (
|
||||
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
||||
@ -2713,6 +3396,19 @@ SecureBootCallback (
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_VALUE_SAVE_AND_EXIT_DBT:
|
||||
Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2);
|
||||
if (EFI_ERROR (Status)) {
|
||||
CreatePopUp (
|
||||
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
||||
&Key,
|
||||
L"ERROR: Unsupported file type!",
|
||||
L"Only supports DER-encoded X509 certificate.",
|
||||
NULL
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (QuestionId >= FILE_OPTION_GOTO_OFFSET) {
|
||||
UpdateFileExplorer (Private, QuestionId);
|
||||
@ -2741,6 +3437,17 @@ SecureBootCallback (
|
||||
OPTION_DEL_DBX_QUESTION_ID,
|
||||
QuestionId - OPTION_DEL_DBX_QUESTION_ID
|
||||
);
|
||||
} else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) &&
|
||||
(QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) {
|
||||
DeleteSignature (
|
||||
Private,
|
||||
EFI_IMAGE_SECURITY_DATABASE2,
|
||||
&gEfiImageSecurityDatabaseGuid,
|
||||
LABEL_DBT_DELETE,
|
||||
SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,
|
||||
OPTION_DEL_DBT_QUESTION_ID,
|
||||
QuestionId - OPTION_DEL_DBT_QUESTION_ID
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2774,6 +3481,7 @@ SecureBootCallback (
|
||||
case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:
|
||||
case KEY_VALUE_NO_SAVE_AND_EXIT_DB:
|
||||
case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:
|
||||
case KEY_VALUE_NO_SAVE_AND_EXIT_DBT:
|
||||
if (Private->FileContext->FHandle != NULL) {
|
||||
CloseFile (Private->FileContext->FHandle);
|
||||
Private->FileContext->FHandle = NULL;
|
||||
@ -2794,6 +3502,7 @@ SecureBootCallback (
|
||||
case KEY_SECURE_BOOT_KEK_GUID:
|
||||
case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:
|
||||
case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:
|
||||
case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT:
|
||||
ASSERT (Private->SignatureGUID != NULL);
|
||||
Status = StringToGuid (
|
||||
IfrNvData->SignatureGuid,
|
||||
|
@ -2,7 +2,7 @@
|
||||
The header file of HII Config Access protocol implementation of SecureBoot
|
||||
configuration module.
|
||||
|
||||
Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
@ -73,9 +73,18 @@ extern EFI_IFR_GUID_LABEL *mEndLabel;
|
||||
//
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
//
|
||||
// Set max digest size as SHA256 Output (32 bytes) by far
|
||||
// SHA-384 digest size in bytes
|
||||
//
|
||||
#define MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
|
||||
#define SHA384_DIGEST_SIZE 48
|
||||
//
|
||||
// SHA-512 digest size in bytes
|
||||
//
|
||||
#define SHA512_DIGEST_SIZE 64
|
||||
|
||||
//
|
||||
// Set max digest size as SHA512 Output (64 bytes) by far
|
||||
//
|
||||
#define MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
|
||||
|
||||
#define WIN_CERT_UEFI_RSA2048_SIZE 256
|
||||
|
||||
@ -87,6 +96,7 @@ extern EFI_IFR_GUID_LABEL *mEndLabel;
|
||||
#define HASHALG_SHA256 0x00000002
|
||||
#define HASHALG_SHA384 0x00000003
|
||||
#define HASHALG_SHA512 0x00000004
|
||||
#define HASHALG_RAW 0x00000005
|
||||
#define HASHALG_MAX 0x00000005
|
||||
|
||||
|
||||
@ -120,6 +130,7 @@ typedef enum _FILE_EXPLORER_STATE {
|
||||
FileExplorerStateEnrollKekFile,
|
||||
FileExplorerStateEnrollSignatureFileToDb,
|
||||
FileExplorerStateEnrollSignatureFileToDbx,
|
||||
FileExplorerStateEnrollSignatureFileToDbt,
|
||||
FileExplorerStateUnknown
|
||||
} FILE_EXPLORER_STATE;
|
||||
|
||||
|
@ -41,6 +41,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#define FORM_FILE_EXPLORER_ID_KEK 0x11
|
||||
#define FORM_FILE_EXPLORER_ID_DB 0x12
|
||||
#define FORM_FILE_EXPLORER_ID_DBX 0x13
|
||||
#define FORMID_SECURE_BOOT_DBT_OPTION_FORM 0x14
|
||||
#define SECUREBOOT_ENROLL_SIGNATURE_TO_DBT 0x15
|
||||
#define SECUREBOOT_DELETE_SIGNATURE_FROM_DBT 0x16
|
||||
#define FORM_FILE_EXPLORER_ID_DBT 0x17
|
||||
|
||||
#define SECURE_BOOT_MODE_CUSTOM 0x01
|
||||
#define SECURE_BOOT_MODE_STANDARD 0x00
|
||||
@ -56,6 +60,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#define KEY_VALUE_SAVE_AND_EXIT_DBX 0x100a
|
||||
#define KEY_VALUE_NO_SAVE_AND_EXIT_DBX 0x100b
|
||||
#define KEY_HIDE_SECURE_BOOT 0x100c
|
||||
#define KEY_VALUE_SAVE_AND_EXIT_DBT 0x100d
|
||||
#define KEY_VALUE_NO_SAVE_AND_EXIT_DBT 0x100e
|
||||
|
||||
#define KEY_SECURE_BOOT_OPTION 0x1100
|
||||
#define KEY_SECURE_BOOT_PK_OPTION 0x1101
|
||||
@ -69,10 +75,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#define KEY_SECURE_BOOT_KEK_GUID 0x110a
|
||||
#define KEY_SECURE_BOOT_SIGNATURE_GUID_DB 0x110b
|
||||
#define KEY_SECURE_BOOT_SIGNATURE_GUID_DBX 0x110c
|
||||
#define KEY_SECURE_BOOT_DBT_OPTION 0x110d
|
||||
#define KEY_SECURE_BOOT_SIGNATURE_GUID_DBT 0x110e
|
||||
|
||||
#define LABEL_KEK_DELETE 0x1200
|
||||
#define LABEL_DB_DELETE 0x1201
|
||||
#define LABEL_DBX_DELETE 0x1202
|
||||
#define LABEL_DBT_DELETE 0x1203
|
||||
#define LABEL_END 0xffff
|
||||
|
||||
#define SECURE_BOOT_MAX_ATTEMPTS_NUM 255
|
||||
@ -95,6 +104,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
//
|
||||
#define OPTION_DEL_DBX_QUESTION_ID 0x4000
|
||||
|
||||
//
|
||||
// Question ID 0x5000 ~ 0x5FFF is for DBT
|
||||
//
|
||||
#define OPTION_DEL_DBT_QUESTION_ID 0x5000
|
||||
|
||||
#define FILE_OPTION_GOTO_OFFSET 0xC000
|
||||
#define FILE_OPTION_OFFSET 0x8000
|
||||
#define FILE_OPTION_MASK 0x3FFF
|
||||
@ -102,18 +116,21 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#define SECURE_BOOT_GUID_SIZE 36
|
||||
#define SECURE_BOOT_GUID_STORAGE_SIZE 37
|
||||
|
||||
|
||||
//
|
||||
// Nv Data structure referenced by IFR
|
||||
//
|
||||
typedef struct {
|
||||
BOOLEAN AttemptSecureBoot; //Attempt to enable/disable Secure Boot.
|
||||
BOOLEAN HideSecureBoot; //Hiden Attempt Secure Boot
|
||||
BOOLEAN AttemptSecureBoot; // Attempt to enable/disable Secure Boot
|
||||
BOOLEAN HideSecureBoot; // Hiden Attempt Secure Boot
|
||||
CHAR16 SignatureGuid[SECURE_BOOT_GUID_STORAGE_SIZE];
|
||||
BOOLEAN PhysicalPresent; //If a Physical Present User;
|
||||
UINT8 SecureBootMode; //Secure Boot Mode: Standard Or Custom
|
||||
BOOLEAN PhysicalPresent; // If a Physical Present User
|
||||
UINT8 SecureBootMode; // Secure Boot Mode: Standard Or Custom
|
||||
BOOLEAN DeletePk;
|
||||
BOOLEAN HasPk; //If Pk is existed it is true;
|
||||
BOOLEAN HasPk; // If Pk is existed it is true
|
||||
BOOLEAN AlwaysRevocation; // If the certificate is always revoked. Revocation time is hidden
|
||||
UINT8 CertificateFormat; // The type of the certificate
|
||||
EFI_HII_DATE RevocationDate; // The revocation date of the certificate
|
||||
EFI_HII_TIME RevocationTime; // The revocation time of the certificate
|
||||
} SECUREBOOT_CONFIGURATION;
|
||||
|
||||
#endif
|
Binary file not shown.
Reference in New Issue
Block a user