Properly retrieve certificate from clover binary when enabling secure boot

This commit is contained in:
apianti 2013-12-06 03:46:50 +00:00
parent 3fdc68bf64
commit f6fe23e8b4
7 changed files with 104 additions and 60 deletions

View File

@ -3,20 +3,24 @@ rem windows batch script for building clover signing tool
rem 2013-12-02 apianti
if defined VCINSTALLDIR goto VisualStudioAvailable
if defined VS100COMNTOOLS (
call "%VS100COMNTOOLS%\vsvars32.bat"
if defined VS110COMNTOOLS (
call "%VS110COMNTOOLS%\vsvars32.bat"
) else (
if defined VS90COMNTOOLS (
call "%VS90COMNTOOLS%\vsvars32.bat"
if defined VS100COMNTOOLS (
call "%VS100COMNTOOLS%\vsvars32.bat"
) else (
if defined VS80COMNTOOLS (
call "%VS80COMNTOOLS%\vsvars32.bat"
if defined VS90COMNTOOLS (
call "%VS90COMNTOOLS%\vsvars32.bat"
) else (
if defined VS71COMNTOOLS (
call "%VS71COMNTOOLS%\vsvars32.bat"
if defined VS80COMNTOOLS (
call "%VS80COMNTOOLS%\vsvars32.bat"
) else (
echo Cannot find Visual Studio, required to build signing tool!
goto failscript
if defined VS71COMNTOOLS (
call "%VS71COMNTOOLS%\vsvars32.bat"
) else (
echo Cannot find Visual Studio, required to build signing tool!
goto failscript
)
)
)
)

View File

@ -330,22 +330,14 @@ STATIC LOADER_ENTRY *CreateLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderO
}
// Ignore this loader if it's self path
FilePathAsString = FileDevicePathFileToStr(SelfLoadedImage->FilePath);
FilePathAsString = FileDevicePathFileToStr(SelfFullDevicePath);
if (FilePathAsString) {
EFI_DEVICE_PATH *DevicePath = FileDevicePath(Volume->DeviceHandle, FilePathAsString);
INTN Comparison = StriCmp(FilePathAsString, LoaderDevicePathString);
FreePool(FilePathAsString);
if (DevicePath) {
CHAR16 *FilePathAsString2 = FileDevicePathToStr(DevicePath);
FreePool(DevicePath);
if (FilePathAsString2) {
INTN Comparison = StriCmp(FilePathAsString2, LoaderDevicePathString);
FreePool(FilePathAsString2);
if (Comparison == 0) {
DBG("skipped because path `%s` is self path!\n", LoaderDevicePathString);
FreePool(LoaderDevicePathString);
return NULL;
}
}
if (Comparison == 0) {
DBG("skipped because path `%s` is self path!\n", LoaderDevicePathString);
FreePool(LoaderDevicePathString);
return NULL;
}
}

View File

@ -53,7 +53,7 @@
// Enable secure boot
VOID EnableSecureBoot(VOID)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_STATUS Status = EFI_NOT_FOUND;
BOOLEAN WantDefaultKeys;
CHAR16 *ErrorString = NULL;
UINTN CloverSignatureSize = 0;
@ -64,22 +64,39 @@ VOID EnableSecureBoot(VOID)
}
// Ask user if they want to use default keys
WantDefaultKeys = YesNoMessage(L"Secure Boot", L"Enroll the default keys too?");
// Get this image's certificate
if (SelfLoadedImage != NULL) {
CloverSignature = GetImageSignatureDatabase(SelfLoadedImage->ImageBase, SelfLoadedImage->ImageSize, &CloverSignatureSize, FALSE);
if (CloverSignature != NULL) {
if (CloverSignatureSize == 0) {
// No signature list found
Status = EFI_NOT_FOUND;
FreePool(CloverSignature);
DBG("Enabling secure boot with%a default keys\n", WantDefaultKeys ? "" : "out");
// Get this image's certificate
if (SelfFullDevicePath != NULL) {
UINT32 AuthenticationStatus = 0;
UINTN FileSize = 0;
// Open the file buffer
VOID *FileBuffer = GetFileBufferByFilePath(FALSE, SelfFullDevicePath, &FileSize, &AuthenticationStatus);
if (FileBuffer != NULL) {
if (FileSize > 0) {
// Retrieve the certificates
CloverSignature = GetImageSignatureDatabase(FileBuffer, FileSize, &CloverSignatureSize, FALSE);
if (CloverSignature != NULL) {
if (CloverSignatureSize > 0) {
// Found signature
Status = EFI_SUCCESS;
} else {
FreePool(CloverSignature);
CloverSignature = NULL;
}
}
}
FreePool(FileBuffer);
}
// Check and alert about image not found
if ((FileBuffer == NULL) || (FileSize == 0)) {
CHAR16 *FilePath = FileDevicePathToStr(SelfFullDevicePath);
if (FilePath != NULL) {
DBG("Failed to load Clover image from %s\n", FilePath);
FreePool(FilePath);
} else {
DBG("Failed to load Clover image\n");
}
} else {
// No signature list found
Status = EFI_NOT_FOUND;
}
} else {
// No signature list found
Status = EFI_NOT_FOUND;
}
if (EFI_ERROR(Status) || (CloverSignature == NULL)) {
ErrorString = L"Clover does not have a certificate";

View File

@ -52,9 +52,9 @@
#endif
#define SECDIR_ALIGNMENT_SIZE 8
#define PKCS1_1_5_SIZE (sizeof(WIN_CERTIFICATE_EFI_PKCS1_15) - 1)
#define PKCS7_SIZE (sizeof(WIN_CERTIFICATE) - 1)
#define EFIGUID_SIZE (sizeof(WIN_CERTIFICATE_UEFI_GUID) - 1)
#define CERT_SIZE (sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16))
#define PKCS1_1_5_SIZE (CERT_SIZE + sizeof(EFI_GUID))
#define EFIGUID_SIZE (CERT_SIZE + sizeof(EFI_GUID))
// Check database for signature
STATIC EFI_STATUS CheckSignatureIsInDatabase(IN VOID *Database,
@ -583,7 +583,7 @@ STATIC VOID *CreateImageSignatureDatabase(IN VOID *FileBuffer,
}
// Check for PE header
PeHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(((UINT8 *)FileBuffer) + PeHeaderOffset);
if (PeHeader.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
if (PeHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
// Invalid PE image
return NULL;
}
@ -753,7 +753,7 @@ VOID *GetImageSignatureDatabase(IN VOID *FileBuffer,
UINT32 PeHeaderOffset;
UINT16 Magic;
// Check parameters
if (DatabaseSize == 0) {
if (DatabaseSize == NULL) {
return NULL;
}
*DatabaseSize = 0;
@ -769,8 +769,9 @@ VOID *GetImageSignatureDatabase(IN VOID *FileBuffer,
}
// Check for PE header
PeHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(((UINT8 *)FileBuffer) + PeHeaderOffset);
if (PeHeader.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
if (PeHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
// Invalid PE image
DBG("Invalid PE image for signature retrieval (no NT signature)\n");
return NULL;
}
// Fix magic number if needed
@ -790,43 +791,48 @@ VOID *GetImageSignatureDatabase(IN VOID *FileBuffer,
// PE32+
SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&(PeHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
}
DBG("Get image database: 0x%X (0x%X)\n");
DBG("Get image database: 0x%X (0x%X) 0x%X 0x%X 0x%X (0x%X)\n", FileBuffer, FileSize, SecDataDir, SecDataDir->VirtualAddress, ((UINT8 *)FileBuffer) + SecDataDir->VirtualAddress, SecDataDir->Size);
// Check the security data directory is found and valid
if ((SecDataDir->VirtualAddress >= FileSize) || ((SecDataDir->VirtualAddress + SecDataDir->Size) > FileSize)) {
DBG("Security directory exceeds the file limits\n");
SecDataDir = NULL;
}
if ((SecDataDir == NULL) || (SecDataDir->Size == 0)) {
if (HashIfNoDatabase) {
// Try to hash the image instead
return CreateImageSignatureDatabase(FileBuffer, FileSize, DatabaseSize);
}
// No certificate
DBG("Security directory not found in image!\n");
return NULL;
}
// There may be multiple certificates so grab each and update signature list
Ptr = (((UINT8 *)FileBuffer) + SecDataDir->VirtualAddress);
End = Ptr + SecDataDir->Size;
while (Ptr < End) {
while ((Ptr + CERT_SIZE) < End) {
WIN_CERTIFICATE *Cert = (WIN_CERTIFICATE *)Ptr;
UINTN Length = Cert->dwLength;
UINTN Alignment = (Length % SECDIR_ALIGNMENT_SIZE);
UINTN SigSize = 0;
VOID *Signature = NULL;
EFI_GUID *SigGuid = NULL;
// Check the signature length
if (Length <= PKCS7_SIZE) {
break;
}
// Get the alignment length
if (Alignment != 0) {
Alignment = SECDIR_ALIGNMENT_SIZE - Alignment;
}
DBG("Embedded certificate: 0x%X (0x%X) [0x%X]\n", Cert, Length, Cert->wCertificateType);
// Get the certificate's type
if (Cert->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
// PKCS#7
Signature = Ptr + PKCS7_SIZE;
SigSize = Length - PKCS7_SIZE;
if (Length < CERT_SIZE) {
break;
}
Signature = Ptr + CERT_SIZE;
SigSize = Length - CERT_SIZE;
SigGuid = &gEfiCertPkcs7Guid;
} else if (Cert->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
// EFI GUID
if (Length <= EFIGUID_SIZE) {
if (Length < EFIGUID_SIZE) {
break;
}
Signature = Ptr + EFIGUID_SIZE;
@ -842,15 +848,13 @@ VOID *GetImageSignatureDatabase(IN VOID *FileBuffer,
}
} else if (Cert->wCertificateType == WIN_CERT_TYPE_EFI_PKCS115) {
// PKCS#1v1.5
if (Length <= PKCS1_1_5_SIZE) {
if (Length < PKCS1_1_5_SIZE) {
break;
}
Signature = Ptr + PKCS1_1_5_SIZE;
SigSize = (Length - PKCS1_1_5_SIZE);
if (SigSize == 256) {
// Only accept 2048 bit key as RSA
SigGuid = &gEfiCertRsa2048Guid;
}
GuidCert = (WIN_CERTIFICATE_UEFI_GUID *)Cert;
SigGuid = &(GuidCert->CertType);
}
// Append the signature if valid
if ((SigGuid != NULL) && (Signature != NULL) && (SigSize > 0)) {
@ -859,7 +863,7 @@ VOID *GetImageSignatureDatabase(IN VOID *FileBuffer,
break;
}
} else {
DBG("Skipping non-signature certificate: 0x%X (0x%X) %d\n", Cert, Length, Cert->wCertificateType);
DBG("Skipping non-signature certificate: 0x%X (0x%X) [0x%X]\n", Cert, Length, Cert->wCertificateType);
}
// Advance to next certificate
Ptr += (Length + Alignment);

View File

@ -75,6 +75,7 @@ EFI_STATUS EnrollSecureBootKeys(IN VOID *AuthorizedDatabase,
VOID *Database = NULL;
if (WantDefaultKeys) {
// Get default authorized database
DBG("Retrieving default authorized database ...\n");
Database = GetSignatureDatabase(DEFAULT_AUTHORIZED_DATABASE_NAME, &DEFAULT_AUTHORIZED_DATABASE_GUID, &DatabaseSize);
if ((DatabaseSize == 0) && (Database != NULL)) {
FreePool(Database);
@ -83,23 +84,32 @@ EFI_STATUS EnrollSecureBootKeys(IN VOID *AuthorizedDatabase,
}
// Set the authorized database
if (Database != NULL) {
DBG("Appending default authorized database to authorized database ...\n");
Status = AppendSignatureDatabaseToDatabase(&Database, &DatabaseSize, AuthorizedDatabase, AuthorizedDatabaseSize);
if (EFI_ERROR(Status)) {
FreePool(Database);
return Status;
}
DBG("Setting authorized database ...\n");
Status = SetAuthorizedDatabase(Database, DatabaseSize);
FreePool(Database);
} else {
// Set clover signature as only
if (WantDefaultKeys) {
DBG("%aetting authorized database ...\n", WantDefaultKeys ? "No default authorized database found, s" : "S");
} else {
DBG("Setting authorized database ...\n");
}
Status = SetAuthorizedDatabase(AuthorizedDatabase, AuthorizedDatabaseSize);
}
if (EFI_ERROR(Status)) {
DBG("Failed to set the authorized database! %r\n", Status);
return Status;
}
// We don't need the unauthorized database
if (WantDefaultKeys) {
// Get the default authorized database
DBG("Retrieving the default unauthorized database ...\n");
DatabaseSize = 0;
Database = GetSignatureDatabase(DEFAULT_UNAUTHORIZED_DATABASE_NAME, &DEFAULT_UNAUTHORIZED_DATABASE_GUID, &DatabaseSize);
if ((DatabaseSize == 0) && (Database != NULL)) {
@ -110,6 +120,12 @@ EFI_STATUS EnrollSecureBootKeys(IN VOID *AuthorizedDatabase,
if (Database != NULL) {
Status = SetSignatureDatabase(DEFAULT_UNAUTHORIZED_DATABASE_NAME, &DEFAULT_UNAUTHORIZED_DATABASE_GUID, Database, DatabaseSize);
FreePool(Database);
if (EFI_ERROR(Status)) {
DBG("Failed to set the unauthorized database! %r\n", Status);
return Status;
}
} else {
DBG("No default unauthorized database found!\n");
}
}
// We need to enroll our own exchange database because we may update databases outside of setup mode
@ -117,20 +133,27 @@ EFI_STATUS EnrollSecureBootKeys(IN VOID *AuthorizedDatabase,
Database = NULL;
if (WantDefaultKeys) {
// Get the default exchange database
DBG("Retrieving default exchange database ...\n");
Database = GetSignatureDatabase(DEFAULT_EXCHANGE_DATABASE_NAME, &DEFAULT_EXCHANGE_DATABASE_GUID, &DatabaseSize);
if ((DatabaseSize == 0) && (Database != NULL)) {
FreePool(Database);
Database = NULL;
}
if (Database == NULL) {
DBG("No default exchange database found\n");
}
}
// Set the exchange database
DBG("Modifying exchange database ...\n");
Status = AppendSignatureToDatabase(&Database, &DatabaseSize, &gEfiCertX509Guid, (VOID *)gSecureBootExchangeKey, sizeof(gSecureBootExchangeKey));
if (EFI_ERROR(Status)) {
if (Database != NULL) {
FreePool(Database);
}
DBG("Failed to modify exchange database! %r\n", Status);
return Status;
}
DBG("Setting the exchange database ...\n");
Status = SetSignatureDatabase(EXCHANGE_DATABASE_NAME, &EXCHANGE_DATABASE_GUID, Database, DatabaseSize);
FreePool(Database);
if (EFI_ERROR(Status)) {
@ -138,6 +161,7 @@ EFI_STATUS EnrollSecureBootKeys(IN VOID *AuthorizedDatabase,
}
// Unsure if default platform database should be enrolled.....???
// Set the platform database - NOT ENROLLING DEFAULT PLATFORM DATABASE, ONLY CLOVER SHOULD OWN PLATFORM(?)
DBG("Setting the platform database ...\n");
return gRT->SetVariable(PLATFORM_DATABASE_NAME, &PLATFORM_DATABASE_GUID, SET_DATABASE_ATTRIBUTES, sizeof(gSecureBootPlatformSignedKey), (VOID *)gSecureBootPlatformSignedKey);
}

View File

@ -57,6 +57,7 @@ EFI_FILE *SelfRootDir;
EFI_FILE *SelfDir;
CHAR16 *SelfDirPath;
EFI_DEVICE_PATH *SelfDevicePath;
EFI_DEVICE_PATH *SelfFullDevicePath;
EFI_FILE *ThemeDir = NULL;
CHAR16 *ThemePath;
BOOLEAN gThemeChanged = FALSE;
@ -161,6 +162,7 @@ EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle)
// find the current directory
FilePathAsString = FileDevicePathToStr(SelfLoadedImage->FilePath);
if (FilePathAsString != NULL) {
SelfFullDevicePath = FileDevicePath(SelfDeviceHandle, FilePathAsString);
for (i = StrLen(FilePathAsString); i > 0 && FilePathAsString[i] != '\\'; i--) ;
if (i > 0) {
FilePathAsString[i] = 0;

View File

@ -450,6 +450,7 @@ extern EFI_FILE *SelfRootDir;
extern EFI_FILE *SelfDir;
extern CHAR16 *SelfDirPath;
extern EFI_DEVICE_PATH *SelfDevicePath;
extern EFI_DEVICE_PATH *SelfFullDevicePath;
extern EFI_FILE *ThemeDir;
extern CHAR16 *ThemePath;
extern EFI_FILE *OEMDir;