mirror of
https://github.com/pbatard/rufus.git
synced 2025-06-08 10:22:30 -04:00
[iso] improve UEFI bootloader reporting
* Add systemd-boot version reporting and fix GRUB version detection for CentOS * Add notes about the various Secure Boot gotchas (log only) * Enable download of remote active/revoked Secure Boot certificate thumbprints * Also rename the ceiling/floor align macros
This commit is contained in:
parent
207a330979
commit
688f011f31
12 changed files with 325 additions and 146 deletions
|
@ -1,3 +1,15 @@
|
|||
o Version 4.8 (2025.06.??)
|
||||
Switch to wimlib for all WIM image processing:
|
||||
- Greatly speeds up image analysis when opening Windows ISOs
|
||||
- Can speed up Windows To Go drive creation (But won't do miracles if you have a crap drive)
|
||||
- Might help with Parallels limitations on Mac (But Rufus on Parallels is still UNSUPPORTED)
|
||||
- Enables the splitting of >4GB files with Alt-E (But still WAY SLOWER than using UEFI:NTFS)
|
||||
Switch to using Visual Studio binaries everywhere, due to MinGW DLL delay-loading limitations
|
||||
Add more exceptions for Linux ISOs that restrict themselves to DD mode (Nobara, openSUSE, ...)
|
||||
Improve reporting of UEFI bootloaders in the log, with info on the Secure Boot status
|
||||
Fix an issue with size limitations when writing an uncompressed VHD back to the same drive
|
||||
Fix a crash when opening the log with the 32-bit MinGW compiled version
|
||||
|
||||
o Version 4.7 (2025.04.09)
|
||||
Add a mechanism to detect and download updated DBXs from the official UEFI repository
|
||||
Add ztsd compression support for disk images
|
||||
|
|
16
src/db.h
16
src/db.h
|
@ -127,24 +127,22 @@ static uint8_t sha256db[] = {
|
|||
* Contains the SHA-1 thumbprints of the issuer certificate of the official
|
||||
* Secure Boot signing authority (i.e. Microsoft).
|
||||
*/
|
||||
static uint8_t certauth[] = {
|
||||
static const char db_sb_active_txt[] =
|
||||
// 'Microsoft Windows Production PCA 2011'
|
||||
0x58, 0x0a, 0x6f, 0x4c, 0xc4, 0xe4, 0xb6, 0x69, 0xb9, 0xeb, 0xdc, 0x1b, 0x2b, 0x3e, 0x08, 0x7b, 0x80, 0xd0, 0x67, 0x8d,
|
||||
"580a6f4cc4e4b669b9ebdc1b2b3e087b80d0678d\n"
|
||||
// 'Microsoft Corporation UEFI CA 2011'
|
||||
0x46, 0xde, 0xf6, 0x3b, 0x5c, 0xe6, 0x1c, 0xf8, 0xba, 0x0d, 0xe2, 0xe6, 0x63, 0x9c, 0x10, 0x19, 0xd0, 0xed, 0x14, 0xf3,
|
||||
"46def63b5ce61cf8ba0de2e6639c1019d0ed14f3\n"
|
||||
// 'Windows UEFI CA 2023'
|
||||
0x45, 0xa0, 0xfa, 0x32, 0x60, 0x47, 0x73, 0xc8, 0x24, 0x33, 0xc3, 0xb7, 0xd5, 0x9e, 0x74, 0x66, 0xb3, 0xac, 0x0c, 0x67,
|
||||
"45a0fa32604773c82433c3b7d59e7466b3ac0c67\n"
|
||||
// 'Microsoft UEFI CA 2023'
|
||||
0xb5, 0xee, 0xb4, 0xa6, 0x70, 0x60, 0x48, 0x07, 0x3f, 0x0e, 0xd2, 0x96, 0xe7, 0xf5, 0x80, 0xa7, 0x90, 0xb5, 0x9e, 0xaa,
|
||||
};
|
||||
"b5eeb4a6706048073f0ed296e7f580a790b59eaa";
|
||||
|
||||
/*
|
||||
* Contains the SHA-1 thumbprints of certificates that are being revoked by DBX.
|
||||
* This only includes the 'Microsoft Windows Production PCA 2011' for now.
|
||||
*/
|
||||
static uint8_t certdbx[] = {
|
||||
0x58, 0x0a, 0x6f, 0x4c, 0xc4, 0xe4, 0xb6, 0x69, 0xb9, 0xeb, 0xdc, 0x1b, 0x2b, 0x3e, 0x08, 0x7b, 0x80, 0xd0, 0x67, 0x8d,
|
||||
};
|
||||
static const char db_sb_revoked_txt[] =
|
||||
"580a6f4cc4e4b669b9ebdc1b2b3e087b80d0678d";
|
||||
|
||||
/*
|
||||
* Extended SBATLevel.txt that merges Linux SBAT with Microsoft's SVN
|
||||
|
|
24
src/drive.c
24
src/drive.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Rufus: The Reliable USB Formatting Utility
|
||||
* Drive access function calls
|
||||
* Copyright © 2011-2024 Pete Batard <pete@akeo.ie>
|
||||
* Copyright © 2011-2025 Pete Batard <pete@akeo.ie>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -2299,7 +2299,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
|||
// CHS sizes that IBM imparted upon us. Long story short, we now align to a
|
||||
// cylinder size that is itself aligned to the cluster size.
|
||||
// If this actually breaks old systems, please send your complaints to IBM.
|
||||
SelectedDrive.Partition[pi].Offset = HI_ALIGN_X_TO_Y(bytes_per_track, ClusterSize);
|
||||
SelectedDrive.Partition[pi].Offset = CEILING_ALIGN(bytes_per_track, ClusterSize);
|
||||
// GRUB2 no longer fits in the usual 31½ KB that the above computation provides
|
||||
// so just unconditionally double that size and get on with it.
|
||||
SelectedDrive.Partition[pi].Offset *= 2;
|
||||
|
@ -2316,9 +2316,9 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
|||
SelectedDrive.Partition[pi].Size = esp_size;
|
||||
SelectedDrive.Partition[pi + 1].Offset = SelectedDrive.Partition[pi].Offset + SelectedDrive.Partition[pi].Size;
|
||||
// Align next partition to track and cluster
|
||||
SelectedDrive.Partition[pi + 1].Offset = HI_ALIGN_X_TO_Y(SelectedDrive.Partition[pi + 1].Offset, bytes_per_track);
|
||||
SelectedDrive.Partition[pi + 1].Offset = CEILING_ALIGN(SelectedDrive.Partition[pi + 1].Offset, bytes_per_track);
|
||||
if (ClusterSize % SelectedDrive.SectorSize == 0)
|
||||
SelectedDrive.Partition[pi + 1].Offset = LO_ALIGN_X_TO_Y(SelectedDrive.Partition[pi + 1].Offset, ClusterSize);
|
||||
SelectedDrive.Partition[pi + 1].Offset = FLOOR_ALIGN(SelectedDrive.Partition[pi + 1].Offset, ClusterSize);
|
||||
assert(SelectedDrive.Partition[pi + 1].Offset >= SelectedDrive.Partition[pi].Offset + SelectedDrive.Partition[pi].Size);
|
||||
pi++;
|
||||
// Clear the extra partition we processed
|
||||
|
@ -2331,9 +2331,9 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
|||
wcscpy(SelectedDrive.Partition[pi].Name, L"Microsoft Reserved Partition");
|
||||
SelectedDrive.Partition[pi].Size = 128 * MB;
|
||||
SelectedDrive.Partition[pi + 1].Offset = SelectedDrive.Partition[pi].Offset + SelectedDrive.Partition[pi].Size;
|
||||
SelectedDrive.Partition[pi + 1].Offset = HI_ALIGN_X_TO_Y(SelectedDrive.Partition[pi + 1].Offset, bytes_per_track);
|
||||
SelectedDrive.Partition[pi + 1].Offset = CEILING_ALIGN(SelectedDrive.Partition[pi + 1].Offset, bytes_per_track);
|
||||
if (ClusterSize % SelectedDrive.SectorSize == 0)
|
||||
SelectedDrive.Partition[pi + 1].Offset = LO_ALIGN_X_TO_Y(SelectedDrive.Partition[pi + 1].Offset, ClusterSize);
|
||||
SelectedDrive.Partition[pi + 1].Offset = FLOOR_ALIGN(SelectedDrive.Partition[pi + 1].Offset, ClusterSize);
|
||||
assert(SelectedDrive.Partition[pi + 1].Offset >= SelectedDrive.Partition[pi].Offset + SelectedDrive.Partition[pi].Size);
|
||||
pi++;
|
||||
extra_partitions &= ~(XP_MSR);
|
||||
|
@ -2352,16 +2352,16 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
|||
assert(persistence_size != 0);
|
||||
partition_index[PI_CASPER] = pi;
|
||||
wcscpy(SelectedDrive.Partition[pi].Name, L"Linux Persistence");
|
||||
SelectedDrive.Partition[pi++].Size = HI_ALIGN_X_TO_Y(persistence_size, bytes_per_track);
|
||||
SelectedDrive.Partition[pi++].Size = CEILING_ALIGN(persistence_size, bytes_per_track);
|
||||
}
|
||||
if (extra_partitions & XP_ESP) {
|
||||
partition_index[PI_ESP] = pi;
|
||||
wcscpy(SelectedDrive.Partition[pi].Name, L"EFI System Partition");
|
||||
SelectedDrive.Partition[pi++].Size = HI_ALIGN_X_TO_Y(esp_size, bytes_per_track);
|
||||
SelectedDrive.Partition[pi++].Size = CEILING_ALIGN(esp_size, bytes_per_track);
|
||||
} else if (extra_partitions & XP_UEFI_NTFS) {
|
||||
partition_index[PI_UEFI_NTFS] = pi;
|
||||
wcscpy(SelectedDrive.Partition[pi].Name, L"UEFI:NTFS");
|
||||
SelectedDrive.Partition[pi++].Size = HI_ALIGN_X_TO_Y(uefi_ntfs_size, bytes_per_track);
|
||||
SelectedDrive.Partition[pi++].Size = CEILING_ALIGN(uefi_ntfs_size, bytes_per_track);
|
||||
} else if (extra_partitions & XP_COMPAT) {
|
||||
wcscpy(SelectedDrive.Partition[pi].Name, L"BIOS Compatibility");
|
||||
SelectedDrive.Partition[pi++].Size = bytes_per_track; // One track for the extra partition
|
||||
|
@ -2377,13 +2377,13 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
|||
last_offset -= 33ULL * SelectedDrive.SectorSize;
|
||||
for (i = pi - 1; i > mi; i--) {
|
||||
assert(SelectedDrive.Partition[i].Size < last_offset);
|
||||
SelectedDrive.Partition[i].Offset = LO_ALIGN_X_TO_Y(last_offset - SelectedDrive.Partition[i].Size, bytes_per_track);
|
||||
SelectedDrive.Partition[i].Offset = FLOOR_ALIGN(last_offset - SelectedDrive.Partition[i].Size, bytes_per_track);
|
||||
last_offset = SelectedDrive.Partition[i].Offset;
|
||||
}
|
||||
|
||||
// With the above, Compute the main partition size (which we align to a track)
|
||||
assert(last_offset > SelectedDrive.Partition[mi].Offset);
|
||||
SelectedDrive.Partition[mi].Size = LO_ALIGN_X_TO_Y(last_offset - SelectedDrive.Partition[mi].Offset, bytes_per_track);
|
||||
SelectedDrive.Partition[mi].Size = FLOOR_ALIGN(last_offset - SelectedDrive.Partition[mi].Offset, bytes_per_track);
|
||||
// Try to make sure that the main partition size is a multiple of the cluster size
|
||||
// This can be especially important when trying to capture an NTFS partition as FFU, as, when
|
||||
// the NTFS partition is aligned to cluster size, the FFU capture parses the NTFS allocated
|
||||
|
@ -2391,7 +2391,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
|||
// a full sector by sector scan of the NTFS partition and records any non-zero garbage, which
|
||||
// may include garbage leftover data from a previous reformat...
|
||||
if (ClusterSize % SelectedDrive.SectorSize == 0)
|
||||
SelectedDrive.Partition[mi].Size = LO_ALIGN_X_TO_Y(SelectedDrive.Partition[mi].Size, ClusterSize);
|
||||
SelectedDrive.Partition[mi].Size = FLOOR_ALIGN(SelectedDrive.Partition[mi].Size, ClusterSize);
|
||||
if (SelectedDrive.Partition[mi].Size <= 0) {
|
||||
uprintf("Error: Invalid %S size", SelectedDrive.Partition[mi].Name);
|
||||
return FALSE;
|
||||
|
|
|
@ -1372,9 +1372,9 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive)
|
|||
|
||||
// 2. WriteFile fails unless the size is a multiple of sector size
|
||||
if (read_size[read_bufnum] % SelectedDrive.SectorSize != 0) {
|
||||
if_not_assert(HI_ALIGN_X_TO_Y(read_size[read_bufnum], SelectedDrive.SectorSize) <= buf_size)
|
||||
if_not_assert(CEILING_ALIGN(read_size[read_bufnum], SelectedDrive.SectorSize) <= buf_size)
|
||||
goto out;
|
||||
read_size[read_bufnum] = HI_ALIGN_X_TO_Y(read_size[read_bufnum], SelectedDrive.SectorSize);
|
||||
read_size[read_bufnum] = CEILING_ALIGN(read_size[read_bufnum], SelectedDrive.SectorSize);
|
||||
}
|
||||
|
||||
// 3. Switch to the next reading buffer
|
||||
|
|
98
src/hash.c
98
src/hash.c
|
@ -114,7 +114,7 @@ StrArray modified_files = { 0 };
|
|||
|
||||
extern int default_thread_priority;
|
||||
extern const char* efi_archname[ARCH_MAX];
|
||||
extern char* sbat_level_txt;
|
||||
extern char *sbat_level_txt, *sb_active_txt, *sb_revoked_txt;
|
||||
extern BOOL expert_mode, usb_debug;
|
||||
|
||||
/*
|
||||
|
@ -2162,6 +2162,12 @@ static BOOL IsRevokedBySbat(uint8_t* buf, uint32_t len)
|
|||
uint32_t i, j, sbat_len;
|
||||
sbat_entry_t entry;
|
||||
|
||||
// Fall back to embedded sbat_level.txt if we couldn't access remote
|
||||
if (sbat_entries == NULL) {
|
||||
sbat_level_txt = safe_strdup(db_sbat_level_txt);
|
||||
sbat_entries = GetSbatEntries(sbat_level_txt);
|
||||
}
|
||||
assert(sbat_entries != NULL);
|
||||
if (sbat_entries == NULL)
|
||||
return FALSE;
|
||||
|
||||
|
@ -2239,7 +2245,7 @@ static BOOL IsRevokedByDbx(uint8_t* hash, uint8_t* buf, uint32_t len)
|
|||
goto out;
|
||||
// Expect SHA-256 hashes
|
||||
if (!CompareGUID(&efi_sig_list->SignatureType, &EFI_CERT_SHA256_GUID)) {
|
||||
uprintf("WARNING: %s is not using SHA-256 hashes - Cannot check for UEFI revocation!", dbx_name);
|
||||
uprintf(" Warning: %s is not using SHA-256 hashes - Cannot check for UEFI revocation!", dbx_name);
|
||||
goto out;
|
||||
}
|
||||
fluff_size += efi_sig_list->SignatureHeaderSize;
|
||||
|
@ -2301,7 +2307,7 @@ static BOOL IsRevokedBySvn(uint8_t* buf, uint32_t len)
|
|||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
uprintf("WARNING: Unexpected Secure Version Number size");
|
||||
uprintf(" Warning: Unexpected Secure Version Number size");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2310,13 +2316,24 @@ static BOOL IsRevokedBySvn(uint8_t* buf, uint32_t len)
|
|||
|
||||
static BOOL IsRevokedByCert(cert_info_t* info)
|
||||
{
|
||||
int i;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < ARRAYSIZE(certdbx); i += SHA1_HASHSIZE) {
|
||||
// TODO: Enable this for non expert mode after enforcement of PCA2011 cert revocation
|
||||
if (!expert_mode)
|
||||
continue;
|
||||
if (memcmp(info->thumbprint, &certdbx[i], SHA1_HASHSIZE) == 0) {
|
||||
uprintf("Found '%s' revoked certificate", info->name);
|
||||
return FALSE;
|
||||
|
||||
// Fall back to embedded Secure Boot thumbprints if we couldn't access remote
|
||||
if (sb_revoked_certs == NULL) {
|
||||
sb_revoked_txt = safe_strdup(db_sb_revoked_txt);
|
||||
sb_revoked_certs = GetThumbprintEntries(sb_revoked_txt);
|
||||
}
|
||||
assert(sb_revoked_certs != NULL && sb_revoked_certs->count != 0);
|
||||
if (sb_revoked_certs == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < sb_revoked_certs->count; i++) {
|
||||
if (memcmp(info->thumbprint, sb_revoked_certs->list[i], SHA1_HASHSIZE) == 0) {
|
||||
uuprintf(" Found '%s' revoked certificate", info->name);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -2325,7 +2342,7 @@ static BOOL IsRevokedByCert(cert_info_t* info)
|
|||
|
||||
BOOL IsSignedBySecureBootAuthority(uint8_t* buf, uint32_t len)
|
||||
{
|
||||
int i;
|
||||
uint32_t i;
|
||||
uint8_t* cert;
|
||||
cert_info_t info;
|
||||
|
||||
|
@ -2337,8 +2354,19 @@ BOOL IsSignedBySecureBootAuthority(uint8_t* buf, uint32_t len)
|
|||
// Secure Boot Authority is always an issuer
|
||||
if (GetIssuerCertificateInfo(cert, &info) != 2)
|
||||
return FALSE;
|
||||
for (i = 0; i < ARRAYSIZE(certauth); i += SHA1_HASHSIZE) {
|
||||
if (memcmp(info.thumbprint, &certauth[i], SHA1_HASHSIZE) == 0)
|
||||
|
||||
// Fall back to embedded Secure Boot thumbprints if we couldn't access remote
|
||||
if (sb_active_certs == NULL) {
|
||||
sb_active_txt = safe_strdup(db_sb_active_txt);
|
||||
sb_active_certs = GetThumbprintEntries(sb_active_txt);
|
||||
}
|
||||
// If we still manage to get an empty list at this stage, I sure wanna know about it!
|
||||
assert(sb_active_certs != NULL && sb_active_certs->count != 0);
|
||||
if (sb_active_certs == NULL || sb_active_certs->count == 0)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < sb_active_certs->count; i++) {
|
||||
if (memcmp(info.thumbprint, sb_active_certs->list[i], SHA1_HASHSIZE) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
@ -2352,13 +2380,7 @@ int IsBootloaderRevoked(uint8_t* buf, uint32_t len)
|
|||
IMAGE_NT_HEADERS32* pe_header;
|
||||
uint8_t* cert;
|
||||
cert_info_t info;
|
||||
int r;
|
||||
|
||||
// Fall back to embedded sbat_level.txt if we couldn't access remote
|
||||
if (sbat_entries == NULL) {
|
||||
sbat_level_txt = safe_strdup(db_sbat_level_txt);
|
||||
sbat_entries = GetSbatEntries(sbat_level_txt);
|
||||
}
|
||||
int r, revoked = 0;
|
||||
|
||||
if (buf == NULL || len < 0x100 || dos_header->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return -2;
|
||||
|
@ -2370,29 +2392,45 @@ int IsBootloaderRevoked(uint8_t* buf, uint32_t len)
|
|||
cert = GetPeSignatureData(buf);
|
||||
r = GetIssuerCertificateInfo(cert, &info);
|
||||
if (r == 0)
|
||||
uuprintf(" (Unsigned Bootloader)");
|
||||
uprintf(" (Unsigned Bootloader)");
|
||||
else if (r > 0)
|
||||
uuprintf(" Signed by: %s", info.name);
|
||||
uprintf(" Signed by '%s'", info.name);
|
||||
|
||||
if (!PE256Buffer(buf, len, hash))
|
||||
return -1;
|
||||
// Check for UEFI DBX revocation
|
||||
if (IsRevokedByDbx(hash, buf, len))
|
||||
return 1;
|
||||
revoked = 1;
|
||||
// Check for Microsoft SSP revocation
|
||||
for (i = 0; i < pe256ssp_size * SHA256_HASHSIZE; i += SHA256_HASHSIZE)
|
||||
for (i = 0; revoked == 0 && i < pe256ssp_size * SHA256_HASHSIZE; i += SHA256_HASHSIZE)
|
||||
if (memcmp(hash, &pe256ssp[i], SHA256_HASHSIZE) == 0)
|
||||
return 2;
|
||||
revoked = 2;
|
||||
// Check for Linux SBAT revocation
|
||||
if (IsRevokedBySbat(buf, len))
|
||||
return 3;
|
||||
if (revoked == 0 && IsRevokedBySbat(buf, len))
|
||||
revoked = 3;
|
||||
// Check for Microsoft SVN revocation
|
||||
if (IsRevokedBySvn(buf, len))
|
||||
return 4;
|
||||
if (revoked == 0 && IsRevokedBySvn(buf, len))
|
||||
revoked = 4;
|
||||
// Check for UEFI DBX certificate revocation
|
||||
if (IsRevokedByCert(&info))
|
||||
return 5;
|
||||
return 0;
|
||||
if (revoked == 0 && IsRevokedByCert(&info))
|
||||
revoked = 5;
|
||||
|
||||
// If signed and not revoked, print the various Secure Boot "gotchas"
|
||||
if (r > 0 && revoked == 0) {
|
||||
if (strcmp(info.name, "Microsoft Windows Production PCA 2011") == 0) {
|
||||
uprintf(" Note: This bootloader may fail Secure Boot validation on systems that");
|
||||
uprintf(" have been updated to use the 'Windows UEFI CA 2023' certificate.");
|
||||
} else if (strcmp(info.name, "Windows UEFI CA 2023") == 0) {
|
||||
uprintf(" Note: This bootloader will fail Secure Boot validation on systems that");
|
||||
uprintf(" have not been updated to use the latest Secure Boot certificates");
|
||||
} else if (strcmp(info.name, "Microsoft Corporation UEFI CA 2011") == 0 ||
|
||||
strcmp(info.name, "Microsoft UEFI CA 2023") == 0) {
|
||||
uprintf(" Note: This bootloader may fail Secure Boot validation on *some* systems,");
|
||||
uprintf(" unless you enable \"Microsoft 3rd-party UEFI CA\" in your 'BIOS'.");
|
||||
}
|
||||
}
|
||||
|
||||
return revoked;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
48
src/iso.c
48
src/iso.c
|
@ -1055,9 +1055,13 @@ void GetGrubVersion(char* buf, size_t buf_size, const char* source)
|
|||
if (buf_size > max_string_size) {
|
||||
for (i = 0; i < buf_size - max_string_size; i++) {
|
||||
for (j = 0; j < ARRAYSIZE(grub_version_str); j++) {
|
||||
if (memcmp(&buf[i], grub_version_str[j], strlen(grub_version_str[j]) + 1) == 0)
|
||||
if (memcmp(&buf[i], grub_version_str[j], strlen(grub_version_str[j])) == 0) {
|
||||
// For CentOS, who decided to add a '\n' after "GRUB version %s"
|
||||
if (buf[i + strlen(grub_version_str[j]) + 1] == '\0')
|
||||
i++;
|
||||
static_strcpy(grub_version, &buf[i + strlen(grub_version_str[j]) + 1]);
|
||||
}
|
||||
}
|
||||
if (memcmp(&buf[i], grub_debug_is_enabled_str, strlen(grub_debug_is_enabled_str)) == 0)
|
||||
has_grub_debug_is_enabled = TRUE;
|
||||
}
|
||||
|
@ -1139,6 +1143,37 @@ void GetGrubFs(char* buf, size_t buf_size)
|
|||
}
|
||||
}
|
||||
|
||||
void GetEfiBootInfo(char* buf, size_t buf_size, const char* source)
|
||||
{
|
||||
// Data to help us identify the EFI bootloader type
|
||||
const struct {
|
||||
const char* label;
|
||||
const char* search_string;
|
||||
} boot_info[] = {
|
||||
{ "Shim", "UEFI SHIM\n$Version: "},
|
||||
// NB: There's also an ID=systemd-boot\nVERSION="x.y.z" footer
|
||||
// in the Arch systemd-boot EFI binary, but I'm not sure if we
|
||||
// can count on this metadata footer to always be present...
|
||||
{ "systemd-boot", "#### LoaderInfo: systemd-boot " },
|
||||
};
|
||||
const size_t max_string_size = 64;
|
||||
size_t i, j, k;
|
||||
|
||||
if (buf_size > max_string_size) {
|
||||
for (i = 0; i < buf_size - max_string_size; i++) {
|
||||
for (j = 0; j < ARRAYSIZE(boot_info); j++) {
|
||||
if (memcmp(&buf[i], boot_info[j].search_string, strlen(boot_info[j].search_string)) == 0) {
|
||||
i += strlen(boot_info[j].search_string);
|
||||
for (k = 0; k < 32 && i + k < buf_size - 1 && !isspace(buf[i + k]); k++);
|
||||
buf[i + k] = '\0';
|
||||
uprintf(" Detected %s version: %s (from '%s')", boot_info[j].label, &buf[i], source);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
|
||||
{
|
||||
const char* basedir[] = { "i386", "amd64", "minint" };
|
||||
|
@ -1386,8 +1421,9 @@ out:
|
|||
}
|
||||
}
|
||||
for (j = 0; j < ARRAYSIZE(img_report.efi_boot_entry); j++) {
|
||||
if (!img_report.efi_boot_entry[j].path[0])
|
||||
continue;
|
||||
if (img_report.efi_boot_entry[j].type == EBT_GRUB) {
|
||||
|
||||
size = (size_t)ReadISOFileToBuffer(src_iso, img_report.efi_boot_entry[j].path, &buf);
|
||||
if (size == 0) {
|
||||
uprintf(" Could not read Grub version from '%s'", img_report.efi_boot_entry[j].path);
|
||||
|
@ -1397,6 +1433,14 @@ out:
|
|||
GetGrubFs(buf, size);
|
||||
}
|
||||
safe_free(buf);
|
||||
} else if (img_report.efi_boot_entry[j].type == EBT_MAIN) {
|
||||
size = (size_t)ReadISOFileToBuffer(src_iso, img_report.efi_boot_entry[j].path, &buf);
|
||||
if (size == 0) {
|
||||
uprintf(" Could not parse '%s'", img_report.efi_boot_entry[j].path);
|
||||
} else {
|
||||
GetEfiBootInfo(buf, size, img_report.efi_boot_entry[j].path);
|
||||
}
|
||||
safe_free(buf);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (int)grub_filesystems.Index; i++) {
|
||||
|
|
|
@ -30,10 +30,14 @@
|
|||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define LO_ALIGN_X_TO_Y(x, y) (((x) / (y)) * (y))
|
||||
#define HI_ALIGN_X_TO_Y(x, y) ((((x) + (y) - 1) / (y)) * (y))
|
||||
#define MAP_BIT(bit) do { map[_log2(bit)] = b; b <<= 1; } while(0)
|
||||
|
||||
#define FLOOR_ALIGN(x, y) (((x) / (y)) * (y))
|
||||
#define CEILING_ALIGN(x, y) ((((x) + (y) - 1) / (y)) * (y))
|
||||
|
||||
#define IS_HEXASCII(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))
|
||||
#define FROM_HEXASCII(c) (((c) >= '0' && (c) <= '9') ? (c) - '0' : (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 10 : \
|
||||
(((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 10 : 0 )))
|
||||
|
||||
/*
|
||||
* Prefetch 64 bytes at address m, for read-only operation
|
||||
|
|
81
src/parser.c
81
src/parser.c
|
@ -1582,20 +1582,18 @@ sbat_entry_t* GetSbatEntries(char* sbatlevel)
|
|||
BOOL eol, eof;
|
||||
char* version_str;
|
||||
uint32_t i, num_entries;
|
||||
sbat_entry_t* _sbat_entries;
|
||||
sbat_entry_t* sbat_list;
|
||||
|
||||
if (sbatlevel == NULL)
|
||||
return NULL;
|
||||
|
||||
num_entries = 0;
|
||||
num_entries = 1;
|
||||
for (i = 0; sbatlevel[i] != '\0'; i++)
|
||||
if (sbatlevel[i] == '\n')
|
||||
num_entries++;
|
||||
|
||||
if (num_entries == 0)
|
||||
return NULL;
|
||||
_sbat_entries = calloc(num_entries + 2, sizeof(sbat_entry_t));
|
||||
if (_sbat_entries == NULL)
|
||||
sbat_list = calloc(num_entries + 1, sizeof(sbat_entry_t));
|
||||
if (sbat_list == NULL)
|
||||
return NULL;
|
||||
|
||||
num_entries = 0;
|
||||
|
@ -1611,7 +1609,7 @@ sbat_entry_t* GetSbatEntries(char* sbatlevel)
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
_sbat_entries[num_entries].product = &sbatlevel[i];
|
||||
sbat_list[num_entries].product = &sbatlevel[i];
|
||||
for (; sbatlevel[i] != ',' && sbatlevel[i] != '\0' && sbatlevel[i] != '\n'; i++);
|
||||
if (sbatlevel[i] == '\0' || sbatlevel[i] == '\n')
|
||||
break;
|
||||
|
@ -1625,16 +1623,77 @@ sbat_entry_t* GetSbatEntries(char* sbatlevel)
|
|||
i++;
|
||||
// Allow the provision of an hex version
|
||||
if (version_str[0] == '0' && version_str[1] == 'x')
|
||||
_sbat_entries[num_entries].version = strtoul(version_str, NULL, 16);
|
||||
sbat_list[num_entries].version = strtoul(version_str, NULL, 16);
|
||||
else
|
||||
_sbat_entries[num_entries].version = strtoul(version_str, NULL, 10);
|
||||
sbat_list[num_entries].version = strtoul(version_str, NULL, 10);
|
||||
if (!eol)
|
||||
for (; sbatlevel[i] != '\0' && sbatlevel[i] != '\n'; i++);
|
||||
if (_sbat_entries[num_entries].version != 0)
|
||||
if (sbat_list[num_entries].version != 0)
|
||||
num_entries++;
|
||||
}
|
||||
if (num_entries == 0) {
|
||||
free(sbat_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _sbat_entries;
|
||||
return sbat_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a list of SHA-1 certificate hexascii thumbprints.
|
||||
* List must be freed by the caller.
|
||||
*/
|
||||
|
||||
thumbprint_list_t* GetThumbprintEntries(char* thumbprints_txt)
|
||||
{
|
||||
uint32_t i, j, num_entries;
|
||||
thumbprint_list_t* thumbprints;
|
||||
|
||||
if (thumbprints_txt == NULL)
|
||||
return NULL;
|
||||
|
||||
num_entries = 1;
|
||||
for (i = 0; thumbprints_txt[i] != '\0'; i++)
|
||||
if (thumbprints_txt[i] == '\n')
|
||||
num_entries++;
|
||||
|
||||
thumbprints = malloc(sizeof(thumbprint_list_t) + num_entries * SHA1_HASHSIZE);
|
||||
if (thumbprints == NULL)
|
||||
return NULL;
|
||||
thumbprints->count = 0;
|
||||
|
||||
for (i = 0; thumbprints_txt[i] != '\0'; ) {
|
||||
// Eliminate blank lines
|
||||
if (thumbprints_txt[i] == '\n') {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// Eliminate lines that don't start by an hexadecimal digit
|
||||
if (!IS_HEXASCII(thumbprints_txt[i])) {
|
||||
while (thumbprints_txt[i] != '\n' && thumbprints_txt[i] != '\0')
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
for (j = 0; thumbprints_txt[i] != '\n' && thumbprints_txt[i] != '\0'; i++, j++) {
|
||||
if (!IS_HEXASCII(thumbprints_txt[i]))
|
||||
break;
|
||||
if ((j / 2) >= SHA1_HASHSIZE)
|
||||
break;
|
||||
thumbprints->list[thumbprints->count][j / 2] = thumbprints->list[thumbprints->count][j / 2] << 4;
|
||||
thumbprints->list[thumbprints->count][j / 2] |= FROM_HEXASCII(thumbprints_txt[i]);
|
||||
if (j == 2 * SHA1_HASHSIZE - 1)
|
||||
thumbprints->count++;
|
||||
}
|
||||
while (thumbprints_txt[i] != '\n' && thumbprints_txt[i] != '\0')
|
||||
i++;
|
||||
}
|
||||
|
||||
if (thumbprints->count == 0) {
|
||||
free(thumbprints);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return thumbprints;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
101
src/rufus.c
101
src/rufus.c
|
@ -143,13 +143,14 @@ char embedded_sl_version_ext[2][32];
|
|||
char ClusterSizeLabel[MAX_CLUSTER_SIZES][64];
|
||||
char msgbox[1024], msgbox_title[32], *ini_file = NULL, *image_path = NULL, *short_image_path;
|
||||
char *archive_path = NULL, image_option_txt[128], *fido_url = NULL, *save_image_type = NULL;
|
||||
char* sbat_level_txt = NULL;
|
||||
char *sbat_level_txt = NULL, *sb_active_txt = NULL, *sb_revoked_txt = NULL;
|
||||
StrArray BlockingProcessList, ImageList;
|
||||
// Number of steps for each FS for FCC_STRUCTURE_PROGRESS
|
||||
const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10, 1, 1, 1, 1 };
|
||||
const char* flash_type[BADLOCKS_PATTERN_TYPES] = { "SLC", "MLC", "TLC" };
|
||||
RUFUS_DRIVE rufus_drive[MAX_DRIVES] = { 0 };
|
||||
sbat_entry_t* sbat_entries = NULL;
|
||||
thumbprint_list_t *sb_active_certs = NULL, *sb_revoked_certs = NULL;
|
||||
|
||||
// TODO: Remember to update copyright year in stdlg's AboutCallback() WM_INITDIALOG,
|
||||
// localization_data.sh and the .rc when the year changes!
|
||||
|
@ -1243,6 +1244,42 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void GetBootladerInfo(void)
|
||||
{
|
||||
static const char* revocation_type[] = { "UEFI DBX", "Windows SSP", "Linux SBAT", "Windows SVN", "Cert DBX" };
|
||||
int r;
|
||||
BOOL sb_signed;
|
||||
uint32_t i, len;
|
||||
uint8_t* buf = NULL;
|
||||
|
||||
// Check UEFI bootloaders for revocation
|
||||
if (!IS_EFI_BOOTABLE(img_report))
|
||||
return;
|
||||
|
||||
assert(ARRAYSIZE(img_report.efi_boot_entry) > 0);
|
||||
PrintStatus(0, MSG_351);
|
||||
uprintf("UEFI bootloaders analysis:");
|
||||
for (i = 0; i < ARRAYSIZE(img_report.efi_boot_entry) && img_report.efi_boot_entry[i].path[0] != 0; i++) {
|
||||
len = ReadISOFileToBuffer(image_path, img_report.efi_boot_entry[i].path, &buf);
|
||||
if (len == 0) {
|
||||
uprintf(" Warning: Failed to extract '%s' to check for UEFI Secure Boot info", img_report.efi_boot_entry[i].path);
|
||||
continue;
|
||||
}
|
||||
sb_signed = IsSignedBySecureBootAuthority(buf, len);
|
||||
if (sb_signed)
|
||||
img_report.has_secureboot_bootloader |= 1;
|
||||
uprintf(" • %s%s", img_report.efi_boot_entry[i].path, sb_signed ? "*" : "");
|
||||
r = IsBootloaderRevoked(buf, len);
|
||||
if (r > 0) {
|
||||
assert(r <= ARRAYSIZE(revocation_type));
|
||||
assert(r <= 7);
|
||||
uprintf(" WARNING: '%s' has been revoked by %s", img_report.efi_boot_entry[i].path, revocation_type[r - 1]);
|
||||
img_report.has_secureboot_bootloader |= 1 << r;
|
||||
}
|
||||
safe_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
// The scanning process can be blocking for message processing => use a thread
|
||||
DWORD WINAPI ImageScanThread(LPVOID param)
|
||||
{
|
||||
|
@ -1348,6 +1385,7 @@ DWORD WINAPI ImageScanThread(LPVOID param)
|
|||
}
|
||||
|
||||
if (img_report.is_iso) {
|
||||
GetBootladerInfo();
|
||||
DisplayISOProps();
|
||||
|
||||
for (i = 0; i < ARRAYSIZE(redhat8_derivative); i++) {
|
||||
|
@ -1431,15 +1469,12 @@ out:
|
|||
ExitThread(0);
|
||||
}
|
||||
|
||||
#define MAP_BIT(bit) do { map[_log2(bit)] = b; b <<= 1; } while(0)
|
||||
|
||||
// Likewise, boot check will block message processing => use a thread
|
||||
static DWORD WINAPI BootCheckThread(LPVOID param)
|
||||
{
|
||||
int i, r, rr, username_index = -1;
|
||||
int i, r, username_index = -1;
|
||||
FILE *fd;
|
||||
uint32_t len;
|
||||
uint8_t* buf = NULL;
|
||||
WPARAM ret = BOOTCHECK_CANCEL;
|
||||
BOOL in_files_dir = FALSE, esp_already_asked = FALSE;
|
||||
BOOL is_windows_to_go = ((image_options & IMOP_WINTOGO) && (ComboBox_GetCurItemData(hImageOption) == IMOP_WIN_TO_GO));
|
||||
|
@ -1638,52 +1673,10 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
|||
}
|
||||
}
|
||||
|
||||
// Check UEFI bootloaders for revocation
|
||||
if (IS_EFI_BOOTABLE(img_report)) {
|
||||
BOOL has_secureboot_signed_bootloader = FALSE;
|
||||
assert(ARRAYSIZE(img_report.efi_boot_entry) > 0);
|
||||
PrintStatus(0, MSG_351);
|
||||
uuprintf("UEFI Secure Boot revocation checks:");
|
||||
// Make sure we have at least one regular EFI bootloader that is formally signed
|
||||
// for Secure Boot, since it doesn't make sense to report revocation otherwise.
|
||||
for (i = 0; !has_secureboot_signed_bootloader && i < ARRAYSIZE(img_report.efi_boot_entry) &&
|
||||
img_report.efi_boot_entry[i].path[0] != 0; i++) {
|
||||
if (img_report.efi_boot_entry[i].type == EBT_MAIN) {
|
||||
len = ReadISOFileToBuffer(image_path, img_report.efi_boot_entry[i].path, &buf);
|
||||
if (len == 0) {
|
||||
uprintf("Warning: Failed to extract '%s' to check for UEFI revocation", img_report.efi_boot_entry[i].path);
|
||||
continue;
|
||||
}
|
||||
if (IsSignedBySecureBootAuthority(buf, len))
|
||||
has_secureboot_signed_bootloader = TRUE;
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
if (!has_secureboot_signed_bootloader) {
|
||||
uuprintf(" No Secure Boot signed bootloader found -- skipping");
|
||||
} else {
|
||||
rr = 0;
|
||||
for (i = 0; i < ARRAYSIZE(img_report.efi_boot_entry) && img_report.efi_boot_entry[i].path[0] != 0; i++) {
|
||||
static const char* revocation_type[] = { "UEFI DBX", "Windows SSP", "Linux SBAT", "Windows SVN", "Cert DBX" };
|
||||
len = ReadISOFileToBuffer(image_path, img_report.efi_boot_entry[i].path, &buf);
|
||||
if (len == 0) {
|
||||
uprintf("Warning: Failed to extract '%s' to check for UEFI revocation", img_report.efi_boot_entry[i].path);
|
||||
continue;
|
||||
}
|
||||
uuprintf("• %s", img_report.efi_boot_entry[i].path);
|
||||
r = IsBootloaderRevoked(buf, len);
|
||||
safe_free(buf);
|
||||
if (r > 0) {
|
||||
assert(r <= ARRAYSIZE(revocation_type));
|
||||
if (rr == 0)
|
||||
rr = r;
|
||||
uprintf("Warning: '%s' has been revoked by %s", img_report.efi_boot_entry[i].path, revocation_type[r - 1]);
|
||||
is_bootloader_revoked = TRUE;
|
||||
}
|
||||
}
|
||||
if (rr > 0) {
|
||||
switch (rr) {
|
||||
case 2:
|
||||
// Display an alert if any of the UEFI bootloaders have been revoked
|
||||
if (img_report.has_secureboot_bootloader & 0xfe) {
|
||||
switch (img_report.has_secureboot_bootloader & 0xfe) {
|
||||
case 4:
|
||||
msg = lmprintf(MSG_341, "Error code: 0xc0000428");
|
||||
break;
|
||||
default:
|
||||
|
@ -1695,8 +1688,6 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
|||
if (r == IDCANCEL)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((img_report.projected_size < MAX_ISO_TO_ESP_SIZE) && HAS_REGULAR_EFI(img_report) &&
|
||||
(partition_type == PARTITION_STYLE_GPT) && IS_FAT(fs_type) && !esp_already_asked) {
|
||||
|
@ -4211,6 +4202,10 @@ out:
|
|||
safe_free(pe256ssp);
|
||||
safe_free(sbat_entries);
|
||||
safe_free(sbat_level_txt);
|
||||
safe_free(sb_active_certs);
|
||||
safe_free(sb_active_txt);
|
||||
safe_free(sb_revoked_certs);
|
||||
safe_free(sb_revoked_txt);
|
||||
if (argv != NULL) {
|
||||
for (i = 0; i < argc; i++)
|
||||
safe_free(argv[i]);
|
||||
|
|
21
src/rufus.h
21
src/rufus.h
|
@ -436,6 +436,7 @@ typedef struct {
|
|||
BOOLEAN rh8_derivative;
|
||||
uint16_t winpe;
|
||||
uint16_t has_efi;
|
||||
uint8_t has_secureboot_bootloader;
|
||||
uint8_t has_md5sum;
|
||||
uint8_t wininst_index;
|
||||
uint8_t has_symlinks;
|
||||
|
@ -519,12 +520,6 @@ typedef struct {
|
|||
uint32_t* address; // 32-bit will do, as we're not dealing with >4GB DLLs...
|
||||
} dll_resolver_t;
|
||||
|
||||
/* SBAT entry */
|
||||
typedef struct {
|
||||
char* product;
|
||||
uint32_t version;
|
||||
} sbat_entry_t;
|
||||
|
||||
/* Alignment macro */
|
||||
#if defined(__GNUC__)
|
||||
#define ALIGNED(m) __attribute__ ((__aligned__(m)))
|
||||
|
@ -576,6 +571,18 @@ extern hash_init_t* hash_init[HASH_MAX];
|
|||
extern hash_write_t* hash_write[HASH_MAX];
|
||||
extern hash_final_t* hash_final[HASH_MAX];
|
||||
|
||||
/* SBAT entry */
|
||||
typedef struct {
|
||||
char* product;
|
||||
uint32_t version;
|
||||
} sbat_entry_t;
|
||||
|
||||
/* Certificate thumbprint list */
|
||||
typedef struct {
|
||||
uint32_t count;
|
||||
uint8_t list[0][SHA1_HASHSIZE];
|
||||
} thumbprint_list_t;
|
||||
|
||||
#ifndef __VA_GROUP__
|
||||
#define __VA_GROUP__(...) __VA_ARGS__
|
||||
#endif
|
||||
|
@ -741,6 +748,7 @@ extern const int nb_steps[FS_MAX];
|
|||
extern float fScale;
|
||||
extern windows_version_t WindowsVersion;
|
||||
extern sbat_entry_t* sbat_entries;
|
||||
extern thumbprint_list_t *sb_active_certs, *sb_revoked_certs;
|
||||
extern int dialog_showing, force_update, fs_type, boot_type, partition_type, target_type;
|
||||
extern unsigned long syslinux_ldlinux_len[2];
|
||||
extern char ubuffer[UBUFFER_SIZE], embedded_sl_version_str[2][12];
|
||||
|
@ -886,6 +894,7 @@ extern HANDLE CreatePreallocatedFile(const char* lpFileName, DWORD dwDesiredAcce
|
|||
DWORD dwFlagsAndAttributes, LONGLONG fileSize);
|
||||
extern uint32_t ResolveDllAddress(dll_resolver_t* resolver);
|
||||
extern sbat_entry_t* GetSbatEntries(char* sbatlevel);
|
||||
extern thumbprint_list_t* GetThumbprintEntries(char* thumbprints_txt);
|
||||
extern uint16_t GetPeArch(uint8_t* buf);
|
||||
extern uint8_t* GetPeSection(uint8_t* buf, const char* name, uint32_t* len);
|
||||
extern uint8_t* GetPeSignatureData(uint8_t* buf);
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 4.8.2249"
|
||||
CAPTION "Rufus 4.8.2250"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -407,8 +407,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,8,2249,0
|
||||
PRODUCTVERSION 4,8,2249,0
|
||||
FILEVERSION 4,8,2250,0
|
||||
PRODUCTVERSION 4,8,2250,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -426,13 +426,13 @@ BEGIN
|
|||
VALUE "Comments", "https://rufus.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "4.8.2249"
|
||||
VALUE "FileVersion", "4.8.2250"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2025 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
VALUE "OriginalFilename", "rufus-4.8.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "4.8.2249"
|
||||
VALUE "ProductVersion", "4.8.2250"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
26
src/stdlg.c
26
src/stdlg.c
|
@ -46,7 +46,7 @@
|
|||
|
||||
/* Globals */
|
||||
extern BOOL is_x86_64, appstore_version;
|
||||
extern char unattend_username[MAX_USERNAME_LENGTH], *sbat_level_txt;
|
||||
extern char unattend_username[MAX_USERNAME_LENGTH], *sbat_level_txt, *sb_active_txt, *sb_revoked_txt;
|
||||
extern HICON hSmallIcon, hBigIcon;
|
||||
static HICON hMessageIcon = (HICON)INVALID_HANDLE_VALUE;
|
||||
static char* szMessageText = NULL;
|
||||
|
@ -1404,18 +1404,38 @@ static DWORD WINAPI CheckForFidoThread(LPVOID param)
|
|||
safe_free(fido_url);
|
||||
safe_free(sbat_entries);
|
||||
safe_free(sbat_level_txt);
|
||||
safe_free(sb_active_txt);
|
||||
safe_free(sb_revoked_txt);
|
||||
|
||||
// Get the latest sbat_level.txt data while we're poking the network for Fido.
|
||||
len = DownloadToFileOrBuffer(RUFUS_URL "/sbat_level.txt", NULL, (BYTE**)&sbat_level_txt, NULL, FALSE);
|
||||
if (len != 0 && len < 512) {
|
||||
if (len != 0 && len < 1 * KB) {
|
||||
sbat_entries = GetSbatEntries(sbat_level_txt);
|
||||
if (sbat_entries != 0) {
|
||||
if (sbat_entries != NULL) {
|
||||
for (i = 0; sbat_entries[i].product != NULL; i++);
|
||||
if (i > 0)
|
||||
uprintf("Found %d additional UEFI revocation filters from remote SBAT", i);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the active Secure Boot certificate thumbprints
|
||||
len = DownloadToFileOrBuffer(RUFUS_URL "/sb_active.txt", NULL, (BYTE**)&sb_active_txt, NULL, FALSE);
|
||||
if (len != 0 && len < 1 * KB) {
|
||||
sb_active_certs = GetThumbprintEntries(sb_active_txt);
|
||||
if (sb_active_certs != NULL) {
|
||||
uprintf("Found %d active Secure Boot certificate entries from remote", sb_active_certs->count);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the revoked Secure Boot certificate thumbprints
|
||||
len = DownloadToFileOrBuffer(RUFUS_URL "/sb_revoked.txt", NULL, (BYTE**)&sb_revoked_txt, NULL, FALSE);
|
||||
if (len != 0 && len < 1 * KB) {
|
||||
sb_revoked_certs = GetThumbprintEntries(sb_revoked_txt);
|
||||
if (sb_revoked_certs != NULL) {
|
||||
uprintf("Found %d revoked Secure Boot certificate entries from remote", sb_revoked_certs->count);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the Fido URL from parsing a 'Fido.ver' on our server. This enables the use of different
|
||||
// Fido versions from different versions of Rufus, if needed, as opposed to always downloading
|
||||
// the latest release from GitHub, which may contain incompatible changes...
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue