Properly retrieve certificate from clover binary when enabling secure boot
This commit is contained in:
parent
3fdc68bf64
commit
f6fe23e8b4
|
@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue