From 02369442a2176e84ef005c9f03e124317e9b503b Mon Sep 17 00:00:00 2001 From: Alex Matrosov Date: Sun, 5 Nov 2017 23:10:06 -0800 Subject: [PATCH] NE Alpha 44 + support of MS Surface implementation of Intel Boot Guard + optional disabling Intel Boot Guard marking --- UEFITool/uefitool.cpp | 50 ++++++++++++-------- UEFITool/uefitool.h | 2 + UEFITool/uefitool.ui | 26 +++++++++- common/bootguard.h | 20 ++++++-- common/ffsparser.cpp | 107 +++++++++++++++++++++++++++++------------- common/ffsparser.h | 11 +++-- common/treemodel.cpp | 7 ++- common/treemodel.h | 4 +- 8 files changed, 164 insertions(+), 63 deletions(-) diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index 076d220..5a9fc2c 100644 --- a/UEFITool/uefitool.cpp +++ b/UEFITool/uefitool.cpp @@ -60,6 +60,7 @@ version(tr("NE alpha 44")) connect(ui->actionGoToOffset, SIGNAL(triggered()), this, SLOT(goToOffset())); connect(ui->actionGoToAddress, SIGNAL(triggered()), this, SLOT(goToAddress())); connect(ui->actionLoadGuidDatabase, SIGNAL(triggered()), this, SLOT(loadGuidDatabase())); + connect(ui->actionToggleBootGuardMarking, SIGNAL(toggled(bool)), this, SLOT(toggleBootGuardMarking(bool))); connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(writeSettings())); // Enable Drag-and-Drop actions @@ -198,6 +199,7 @@ void UEFITool::populateUi(const QModelIndex ¤t) || type == Types::EvsaEntry || type == Types::FlashMapEntry); ui->menuStoreActions->setEnabled(type == Types::VssStore + || type == Types::LenovoVssStore || type == Types::FdcStore || type == Types::FsysStore || type == Types::EvsaStore @@ -616,26 +618,27 @@ void UEFITool::extract(const UINT8 mode) QString path; if (mode == EXTRACT_MODE_AS_IS) { switch (type) { - case Types::Capsule: path = QFileDialog::getSaveFileName(this, tr("Save capsule to file"), name + ".cap", "Capsule files (*.cap *.bin);;All files (*)"); break; - case Types::Image: path = QFileDialog::getSaveFileName(this, tr("Save image to file"), name + ".rom", "Image files (*.rom *.bin);;All files (*)"); break; - case Types::Region: path = QFileDialog::getSaveFileName(this, tr("Save region to file"), name + ".rgn", "Region files (*.rgn *.bin);;All files (*)"); break; - case Types::Padding: path = QFileDialog::getSaveFileName(this, tr("Save padding to file"), name + ".pad", "Padding files (*.pad *.bin);;All files (*)"); break; - case Types::Volume: path = QFileDialog::getSaveFileName(this, tr("Save volume to file"), name + ".vol", "Volume files (*.vol *.bin);;All files (*)"); break; - case Types::File: path = QFileDialog::getSaveFileName(this, tr("Save FFS file to file"), name + ".ffs", "FFS files (*.ffs *.bin);;All files (*)"); break; - case Types::Section: path = QFileDialog::getSaveFileName(this, tr("Save section to file"), name + ".sct", "Section files (*.sct *.bin);;All files (*)"); break; - case Types::NvarEntry: path = QFileDialog::getSaveFileName(this, tr("Save NVAR entry to file"), name + ".nvar", "NVAR entry files (*.nvar *.bin);;All files (*)"); break; - case Types::VssEntry: path = QFileDialog::getSaveFileName(this, tr("Save VSS entry to file"), name + ".vss", "VSS entry files (*.vss *.bin);;All files (*)"); break; - case Types::FsysEntry: path = QFileDialog::getSaveFileName(this, tr("Save Fsys entry to file"), name + ".fse", "Fsys entry files (*.fse *.bin);;All files (*)"); break; - case Types::EvsaEntry: path = QFileDialog::getSaveFileName(this, tr("Save EVSA entry to file"), name + ".evse", "EVSA entry files (*.evse *.bin);;All files (*)"); break; - case Types::FlashMapEntry: path = QFileDialog::getSaveFileName(this, tr("Save FlashMap entry to file"), name + ".fme", "FlashMap entry files (*.fme *.bin);;All files (*)"); break; - case Types::VssStore: path = QFileDialog::getSaveFileName(this, tr("Save VSS store to file"), name + ".vss", "VSS store files (*.vss *.bin);;All files (*)"); break; - case Types::FdcStore: path = QFileDialog::getSaveFileName(this, tr("Save FDC store to file"), name + ".fdc", "FDC store files (*.fdc *.bin);;All files (*)"); break; - case Types::FsysStore: path = QFileDialog::getSaveFileName(this, tr("Save Fsys store to file"), name + ".fsys", "Fsys store files (*.fsys *.bin);;All files (*)"); break; - case Types::EvsaStore: path = QFileDialog::getSaveFileName(this, tr("Save EVSA store to file"), name + ".evsa", "EVSA store files (*.evsa *.bin);;All files (*)"); break; - case Types::FtwStore: path = QFileDialog::getSaveFileName(this, tr("Save FTW store to file"), name + ".ftw", "FTW store files (*.ftw *.bin);;All files (*)"); break; - case Types::FlashMapStore: path = QFileDialog::getSaveFileName(this, tr("Save FlashMap store to file"), name + ".fmap", "FlashMap store files (*.fmap *.bin);;All files (*)"); break; - case Types::CmdbStore: path = QFileDialog::getSaveFileName(this, tr("Save CMDB store to file"), name + ".cmdb", "CMDB store files (*.cmdb *.bin);;All files (*)"); break; - case Types::Microcode: path = QFileDialog::getSaveFileName(this, tr("Save microcode binary to file"), name + ".ucd", "Microcode binary files (*.ucd *.bin);;All files (*)"); break; + case Types::Capsule: path = QFileDialog::getSaveFileName(this, tr("Save capsule to file"), name + ".cap", "Capsule files (*.cap *.bin);;All files (*)"); break; + case Types::Image: path = QFileDialog::getSaveFileName(this, tr("Save image to file"), name + ".rom", "Image files (*.rom *.bin);;All files (*)"); break; + case Types::Region: path = QFileDialog::getSaveFileName(this, tr("Save region to file"), name + ".rgn", "Region files (*.rgn *.bin);;All files (*)"); break; + case Types::Padding: path = QFileDialog::getSaveFileName(this, tr("Save padding to file"), name + ".pad", "Padding files (*.pad *.bin);;All files (*)"); break; + case Types::Volume: path = QFileDialog::getSaveFileName(this, tr("Save volume to file"), name + ".vol", "Volume files (*.vol *.bin);;All files (*)"); break; + case Types::File: path = QFileDialog::getSaveFileName(this, tr("Save FFS file to file"), name + ".ffs", "FFS files (*.ffs *.bin);;All files (*)"); break; + case Types::Section: path = QFileDialog::getSaveFileName(this, tr("Save section to file"), name + ".sct", "Section files (*.sct *.bin);;All files (*)"); break; + case Types::NvarEntry: path = QFileDialog::getSaveFileName(this, tr("Save NVAR entry to file"), name + ".nvar", "NVAR entry files (*.nvar *.bin);;All files (*)"); break; + case Types::VssEntry: path = QFileDialog::getSaveFileName(this, tr("Save VSS entry to file"), name + ".vss", "VSS entry files (*.vss *.bin);;All files (*)"); break; + case Types::FsysEntry: path = QFileDialog::getSaveFileName(this, tr("Save Fsys entry to file"), name + ".fse", "Fsys entry files (*.fse *.bin);;All files (*)"); break; + case Types::EvsaEntry: path = QFileDialog::getSaveFileName(this, tr("Save EVSA entry to file"), name + ".evse", "EVSA entry files (*.evse *.bin);;All files (*)"); break; + case Types::FlashMapEntry: path = QFileDialog::getSaveFileName(this, tr("Save FlashMap entry to file"), name + ".fme", "FlashMap entry files (*.fme *.bin);;All files (*)"); break; + case Types::VssStore: path = QFileDialog::getSaveFileName(this, tr("Save VSS store to file"), name + ".vss", "VSS store files (*.vss *.bin);;All files (*)"); break; + case Types::LenovoVssStore: path = QFileDialog::getSaveFileName(this, tr("Save VSS store to file"), name + ".vss", "VSS store files (*.vss *.bin);;All files (*)"); break; + case Types::FdcStore: path = QFileDialog::getSaveFileName(this, tr("Save FDC store to file"), name + ".fdc", "FDC store files (*.fdc *.bin);;All files (*)"); break; + case Types::FsysStore: path = QFileDialog::getSaveFileName(this, tr("Save Fsys store to file"), name + ".fsys", "Fsys store files (*.fsys *.bin);;All files (*)"); break; + case Types::EvsaStore: path = QFileDialog::getSaveFileName(this, tr("Save EVSA store to file"), name + ".evsa", "EVSA store files (*.evsa *.bin);;All files (*)"); break; + case Types::FtwStore: path = QFileDialog::getSaveFileName(this, tr("Save FTW store to file"), name + ".ftw", "FTW store files (*.ftw *.bin);;All files (*)"); break; + case Types::FlashMapStore: path = QFileDialog::getSaveFileName(this, tr("Save FlashMap store to file"), name + ".fmap", "FlashMap store files (*.fmap *.bin);;All files (*)"); break; + case Types::CmdbStore: path = QFileDialog::getSaveFileName(this, tr("Save CMDB store to file"), name + ".cmdb", "CMDB store files (*.cmdb *.bin);;All files (*)"); break; + case Types::Microcode: path = QFileDialog::getSaveFileName(this, tr("Save microcode binary to file"), name + ".ucd", "Microcode binary files (*.ucd *.bin);;All files (*)"); break; case Types::SlicData: if (subtype == Subtypes::PubkeySlicData) path = QFileDialog::getSaveFileName(this, tr("Save SLIC pubkey to file"), name + ".spk", "SLIC pubkey files (*.spk *.bin);;All files (*)"); else path = QFileDialog::getSaveFileName(this, tr("Save SLIC marker to file"), name + ".smk", "SLIC marker files (*.smk *.bin);;All files (*)"); @@ -669,6 +672,7 @@ void UEFITool::extract(const UINT8 mode) case Types::FlashMapEntry: case Types::FsysEntry: path = QFileDialog::getSaveFileName(this, tr("Save entry body to file"), name + ".bin", "Binary files (*.bin);;All files (*)"); break; case Types::VssStore: + case Types::LenovoVssStore: case Types::FtwStore: case Types::FdcStore: case Types::FsysStore: @@ -914,6 +918,11 @@ void UEFITool::clearMessages() ui->actionMessagesClear->setEnabled(false); } +void UEFITool::toggleBootGuardMarking(bool enabled) +{ + model->setMarkingEnabled(enabled); +} + void UEFITool::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasFormat("text/uri-list")) @@ -1032,6 +1041,7 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event) case Types::EvsaEntry: case Types::FlashMapEntry: ui->menuEntryActions->exec(event->globalPos()); break; case Types::VssStore: + case Types::LenovoVssStore: case Types::FdcStore: case Types::FsysStore: case Types::EvsaStore: diff --git a/UEFITool/uefitool.h b/UEFITool/uefitool.h index f8d4f67..4dfa01c 100644 --- a/UEFITool/uefitool.h +++ b/UEFITool/uefitool.h @@ -106,6 +106,8 @@ private slots: void enableMessagesCopyActions(QListWidgetItem* item); void clearMessages(); + void toggleBootGuardMarking(bool enabled); + void about(); void aboutQt(); diff --git a/UEFITool/uefitool.ui b/UEFITool/uefitool.ui index 306e159..98142e5 100644 --- a/UEFITool/uefitool.ui +++ b/UEFITool/uefitool.ui @@ -311,7 +311,7 @@ 0 0 851 - 21 + 31 @@ -532,8 +532,15 @@ + + + &View + + + + @@ -699,6 +706,9 @@ &Quit + + Alt+X + QAction::QuitRole @@ -849,6 +859,20 @@ Ctrl+Shift+G + + + true + + + true + + + &BootGuard marking + + + Ctrl+Shift+B + + diff --git a/common/bootguard.h b/common/bootguard.h index d2520ea..dcefd20 100644 --- a/common/bootguard.h +++ b/common/bootguard.h @@ -53,6 +53,20 @@ typedef struct BG_VENDOR_HASH_FILE_HEADER_AMI_OLD_ // Offset is derived from flash map, will be detected as root volume with DXE core } BG_VENDOR_HASH_FILE_HEADER_AMI_OLD; +typedef struct BG_MICROSOFT_PMDA_HEADER_ +{ + UINT32 Version; + UINT32 NumEntries; +} BG_MICROSOFT_PMDA_HEADER; + +#define BG_MICROSOFT_PMDA_VERSION 0x00000001 + +typedef struct BG_MICROSOFT_PMDA_ENTRY_ +{ + UINT32 Address; + UINT32 Size; + UINT8 Hash[SHA256_DIGEST_SIZE]; +} BG_MICROSOFT_PMDA_ENTRY; // // Intel ACM @@ -66,7 +80,7 @@ typedef struct INTEL_ACM_HEADER_ { UINT32 HeaderType; UINT32 HeaderVersion; UINT16 ChipsetId; - UINT16 Unknown; + UINT16 Flags; UINT32 ModuleVendor; UINT8 DateDay; UINT8 DateMonth; @@ -151,8 +165,8 @@ typedef struct BG_IBB_ELEMENT_ { UINT32 Flags; UINT64 IbbMchBar; UINT64 VtdBar; - UINT32 Unknown1; - UINT32 Unknown2; + UINT32 PmrlBase; + UINT32 PmrlLimit; UINT64 Unknown3; UINT64 Unknown4; SHA256_HASH IbbHash; diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 8eab609..545568f 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -556,7 +556,7 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l const VSCC_TABLE_ENTRY* vsccTableEntry = (const VSCC_TABLE_ENTRY*)(descriptor + ((UINT16)upperMap->VsccTableBase << 4)); info += UString("\nFlash chips in VSCC table:"); UINT8 vsscTableSize = upperMap->VsccTableSize * sizeof(UINT32) / sizeof(VSCC_TABLE_ENTRY); - for (int i = 0; i < vsscTableSize; i++) { + for (UINT8 i = 0; i < vsscTableSize; i++) { info += usprintf("\n%02X%02X%02X (", vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1) + jedecIdToUString(vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1) @@ -982,7 +982,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc } else if (volumeHeader->Revision == 2) { // Acquire alignment - alignment = (UINT32)pow(2.0, (int)(volumeHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); + alignment = (UINT32)pow(2.0, (INT32)(volumeHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); // Check alignment if (!isUnknown && !model->compressed(parent) && ((model->offset(parent) + localOffset - capsuleOffsetFixup) % alignment)) msgUnaligned = true; @@ -3011,6 +3011,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index) for (UINT32 i = 0; i < (UINT32)bgProtectedRanges.size(); i++) { if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_INTEL_BOOT_GUARD) { bgProtectedRangeFound = true; + bgProtectedRanges[i].Offset -= addressDiff; protectedParts += openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size); markProtectedRangeRecursive(index, bgProtectedRanges[i]); } @@ -3085,6 +3086,21 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index) model->findByOffset(bgProtectedRanges[i].Offset)); } + markProtectedRangeRecursive(index, bgProtectedRanges[i]); + } + else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT) { + bgProtectedRanges[i].Offset -= addressDiff; + protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size); + + UByteArray digest(SHA256_DIGEST_SIZE, '\x00'); + sha256(protectedParts.constData(), protectedParts.length(), digest.data()); + + if (digest != bgProtectedRanges[i].Hash) { + msg(usprintf("checkProtectedRanges: Microsoft protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", + bgProtectedRanges[i].Offset, bgProtectedRanges[i].Offset + bgProtectedRanges[i].Size), + model->findByOffset(bgProtectedRanges[i].Offset)); + } + markProtectedRangeRecursive(index, bgProtectedRanges[i]); } } @@ -3164,7 +3180,7 @@ USTATUS FfsParser::parseVendorHashFile(const UByteArray & fileGuid, const UModel for (UINT32 i = 0; i < header->NumEntries; i++) { const BG_VENDOR_HASH_FILE_ENTRY* entry = (const BG_VENDOR_HASH_FILE_ENTRY*)(header + 1) + i; bootGuardInfo += usprintf("\nRelativeOffset: %08Xh Size: %Xh\nHash: ", entry->Offset, entry->Size); - for (int i = 0; i < sizeof(entry->Hash); i++) { + for (UINT8 i = 0; i < sizeof(entry->Hash); i++) { bootGuardInfo += usprintf("%02X", entry->Hash[i]); } } @@ -3203,7 +3219,7 @@ USTATUS FfsParser::parseVendorHashFile(const UByteArray & fileGuid, const UModel for (UINT32 i = 0; i < NumEntries; i++) { const BG_VENDOR_HASH_FILE_ENTRY* entry = (const BG_VENDOR_HASH_FILE_ENTRY*)(model->body(index).constData()) + i; bootGuardInfo += usprintf("\nAddress: %08Xh Size: %Xh\nHash: ", entry->Offset, entry->Size); - for (int i = 0; i < sizeof(entry->Hash); i++) { + for (UINT8 i = 0; i < sizeof(entry->Hash); i++) { bootGuardInfo += usprintf("%02X", entry->Hash[i]); } } @@ -3216,7 +3232,7 @@ USTATUS FfsParser::parseVendorHashFile(const UByteArray & fileGuid, const UModel bootGuardInfo += usprintf("Old AMI hash file found at offset %Xh\nProtected range:", model->offset(fileIndex)); const BG_VENDOR_HASH_FILE_HEADER_AMI_OLD* entry = (const BG_VENDOR_HASH_FILE_HEADER_AMI_OLD*)(model->body(index).constData()); bootGuardInfo += usprintf("\nSize: %Xh\nHash: ", entry->Size); - for (int i = 0; i < sizeof(entry->Hash); i++) { + for (UINT8 i = 0; i < sizeof(entry->Hash); i++) { bootGuardInfo += usprintf("%02X", entry->Hash[i]); } bootGuardInfo += UString("\n------------------------------------------------------------------------\n\n"); @@ -3488,7 +3504,7 @@ USTATUS FfsParser::parseIntelAcm(const UByteArray & acm, const UINT32 localOffse bootGuardInfo += usprintf( "Intel ACM found at offset %Xh\n" "ModuleType: %08Xh HeaderLength: %08Xh HeaderVersion: %08Xh\n" - "ChipsetId: %04Xh Unknown: %04Xh ModuleVendor: %04Xh\n" + "ChipsetId: %04Xh Flags: %04Xh ModuleVendor: %04Xh\n" "Date: %02X.%02X.%04X ModuleSize: %08Xh EntryPoint: %08Xh\n" "AcmSvn: %04Xh Unknown1: %08Xh Unknown2: %08Xh\n" "GdtBase: %08Xh GdtMax: %08Xh SegSel: %08Xh\n" @@ -3498,7 +3514,7 @@ USTATUS FfsParser::parseIntelAcm(const UByteArray & acm, const UINT32 localOffse header->ModuleSize * sizeof(UINT32), header->HeaderVersion, header->ChipsetId, - header->Unknown, + header->Flags, header->ModuleVendor, header->DateDay, header->DateMonth, header->DateYear, header->ModuleSize * sizeof(UINT32), @@ -3514,14 +3530,14 @@ USTATUS FfsParser::parseIntelAcm(const UByteArray & acm, const UINT32 localOffse ); // Add PubKey bootGuardInfo += usprintf("\n\nACM RSA Public Key (Exponent: %Xh):", header->RsaPubExp); - for (int i = 0; i < sizeof(header->RsaPubKey); i++) { + for (UINT16 i = 0; i < sizeof(header->RsaPubKey); i++) { if (i % 32 == 0) bootGuardInfo += UString("\n"); bootGuardInfo += usprintf("%02X", header->RsaPubKey[i]); } // Add RsaSig bootGuardInfo += UString("\n\nACM RSA Signature:"); - for (int i = 0; i < sizeof(header->RsaSig); i++) { + for (UINT16 i = 0; i < sizeof(header->RsaSig); i++) { if (i % 32 == 0) bootGuardInfo += UString("\n"); bootGuardInfo += usprintf("%02X", header->RsaSig[i]); @@ -3565,7 +3581,7 @@ USTATUS FfsParser::parseIntelBootGuardKeyManifest(const UByteArray & keyManifest ); // Add BpKeyHash bootGuardInfo += UString("\n\nBoot Policy RSA Public Key Hash:\n"); - for (int i = 0; i < sizeof(header->BpKeyHash.HashBuffer); i++) { + for (UINT8 i = 0; i < sizeof(header->BpKeyHash.HashBuffer); i++) { bootGuardInfo += usprintf("%02X", header->BpKeyHash.HashBuffer[i]); } bgKmHash = UByteArray((const char*)header->BpKeyHash.HashBuffer, sizeof(header->BpKeyHash.HashBuffer)); @@ -3573,14 +3589,14 @@ USTATUS FfsParser::parseIntelBootGuardKeyManifest(const UByteArray & keyManifest // Add Key Manifest PubKey bootGuardInfo += usprintf("\n\nKey Manifest RSA Public Key (Exponent: %Xh):", header->KeyManifestSignature.PubKey.Exponent); - for (int i = 0; i < sizeof(header->KeyManifestSignature.PubKey.Modulus); i++) { + for (UINT16 i = 0; i < sizeof(header->KeyManifestSignature.PubKey.Modulus); i++) { if (i % 32 == 0) bootGuardInfo += UString("\n"); bootGuardInfo += usprintf("%02X", header->KeyManifestSignature.PubKey.Modulus[i]); } // Add Key Manifest Signature bootGuardInfo += UString("\n\nKey Manifest RSA Signature:"); - for (int i = 0; i < sizeof(header->KeyManifestSignature.Signature.Signature); i++) { + for (UINT16 i = 0; i < sizeof(header->KeyManifestSignature.Signature.Signature); i++) { if (i % 32 == 0) bootGuardInfo += UString("\n"); bootGuardInfo += usprintf("%02X", header->KeyManifestSignature.Signature.Signature[i]); @@ -3595,7 +3611,7 @@ USTATUS FfsParser::parseIntelBootGuardKeyManifest(const UByteArray & keyManifest return U_INVALID_BG_KEY_MANIFEST; } -USTATUS FfsParser::findNextElement(const UByteArray & bootPolicy, const UINT32 localOffset, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize) +USTATUS FfsParser::findNextElement(const UByteArray & bootPolicy, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize) { UINT32 dataSize = bootPolicy.size(); @@ -3615,7 +3631,7 @@ USTATUS FfsParser::findNextElement(const UByteArray & bootPolicy, const UINT32 l } } else if (*currentPos == BG_BOOT_POLICY_MANIFEST_PLATFORM_MANUFACTURER_ELEMENT_TAG && offset + sizeof(BG_PLATFORM_MANUFACTURER_ELEMENT) < dataSize) { - const BG_PLATFORM_MANUFACTURER_ELEMENT* header = (const BG_PLATFORM_MANUFACTURER_ELEMENT*)(bootPolicy.constData() + localOffset + elementOffset); + const BG_PLATFORM_MANUFACTURER_ELEMENT* header = (const BG_PLATFORM_MANUFACTURER_ELEMENT*)currentPos; // Check that data is present if (offset + sizeof(BG_PLATFORM_MANUFACTURER_ELEMENT) + header->DataSize < dataSize) { nextElementOffset = offset; @@ -3665,7 +3681,7 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, // Iterate over elements to get them all UINT32 elementOffset = 0; UINT32 elementSize = 0; - USTATUS status = findNextElement(bootPolicy, localOffset, localOffset + sizeof(BG_BOOT_POLICY_MANIFEST_HEADER), elementOffset, elementSize); + USTATUS status = findNextElement(bootPolicy, localOffset + sizeof(BG_BOOT_POLICY_MANIFEST_HEADER), elementOffset, elementSize); while (status == U_SUCCESS) { const UINT64* currentPos = (const UINT64*)(bootPolicy.constData() + elementOffset); if (*currentPos == BG_BOOT_POLICY_MANIFEST_IBB_ELEMENT_TAG) { @@ -3675,38 +3691,38 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, "\nInitial Boot Block Element found at offset %Xh\n" "Tag: __IBBS__ Version: %02Xh Unknown: %02Xh\n" "Flags: %08Xh IbbMchBar: %08Xh VtdBar: %08Xh\n" - "Unknown1: %08Xh Unknown2: %08Xh EntryPoint: %08Xh", + "PmrlBase: %08Xh PmrlLimit: %08Xh EntryPoint: %08Xh", model->offset(parent) + localOffset + elementOffset, elementHeader->Version, elementHeader->Unknown, elementHeader->Flags, elementHeader->IbbMchBar, elementHeader->VtdBar, - elementHeader->Unknown1, - elementHeader->Unknown2, + elementHeader->PmrlBase, + elementHeader->PmrlLimit, elementHeader->EntryPoint ); // Add PostIbbHash bootGuardInfo += UString("\n\nPost IBB Hash:\n"); - for (int i = 0; i < sizeof(elementHeader->IbbHash.HashBuffer); i++) { + for (UINT8 i = 0; i < sizeof(elementHeader->IbbHash.HashBuffer); i++) { bootGuardInfo += usprintf("%02X", elementHeader->IbbHash.HashBuffer[i]); } // Add Digest bgBpDigest = UByteArray((const char*)elementHeader->Digest.HashBuffer, sizeof(elementHeader->Digest.HashBuffer)); bootGuardInfo += UString("\n\nIBB Digest:\n"); - for (int i = 0; i < bgBpDigest.size(); i++) { + for (UINT8 i = 0; i < (UINT8)bgBpDigest.size(); i++) { bootGuardInfo += usprintf("%02X", (UINT8)bgBpDigest.at(i)); } // Add all IBB segments bootGuardInfo += UString("\n\nIBB Segments:\n"); const BG_IBB_SEGMENT_ELEMENT* segments = (const BG_IBB_SEGMENT_ELEMENT*)(elementHeader + 1); - for (int i = 0; i < elementHeader->IbbSegCount; i++) { + for (UINT8 i = 0; i < elementHeader->IbbSegCount; i++) { bootGuardInfo += usprintf("Flags: %04Xh Address: %08Xh Size: %08Xh\n", segments[i].Flags, segments[i].Base, segments[i].Size); if (segments[i].Flags == BG_IBB_SEGMENT_FLAG_IBB) { BG_PROTECTED_RANGE range; - range.Offset = segments[i].Base - addressDiff; + range.Offset = segments[i].Base; range.Size = segments[i].Size; range.Type = BG_PROTECTED_RANGE_INTEL_BOOT_GUARD; bgProtectedRanges.push_back(range); @@ -3717,17 +3733,44 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, const BG_PLATFORM_MANUFACTURER_ELEMENT* elementHeader = (const BG_PLATFORM_MANUFACTURER_ELEMENT*)currentPos; bootGuardInfo += usprintf( "\nPlatform Manufacturer Data Element found at offset %Xh\n" - "Tag: __PMDA__ Version: %02Xh DataSize: %02Xh\n", + "Tag: __PMDA__ Version: %02Xh DataSize: %02Xh", model->offset(parent) + localOffset + elementOffset, elementHeader->Version, elementHeader->DataSize ); - // Add data - UINT8* data = (UINT8*)(elementHeader + 1); - for (int i = 0; i < elementHeader->DataSize; i++) { - if (i % 32 == 0) + // Check for Microsoft PMDA hash data + const BG_MICROSOFT_PMDA_HEADER* header = (const BG_MICROSOFT_PMDA_HEADER*)(elementHeader + 1); + if (header->Version == BG_MICROSOFT_PMDA_VERSION + && elementHeader->DataSize == sizeof(BG_MICROSOFT_PMDA_HEADER) + sizeof(BG_MICROSOFT_PMDA_ENTRY)*header->NumEntries) { + // Add entries + bootGuardInfo += UString("\nMicrosoft PMDA-based protected ranges:\n"); + const BG_MICROSOFT_PMDA_ENTRY* entries = (const BG_MICROSOFT_PMDA_ENTRY*)(header + 1); + for (UINT32 i = 0; i < header->NumEntries; i++) { + + bootGuardInfo += usprintf("Address: %08Xh Size: %08Xh\n", entries[i].Address, entries[i].Size); + bootGuardInfo += UString("Hash: "); + for (UINT8 j = 0; j < sizeof(entries[i].Hash); j++) { + bootGuardInfo += usprintf("%02X", entries[i].Hash[j]); + } bootGuardInfo += UString("\n"); - bootGuardInfo += usprintf("%02X", data[i]); + + BG_PROTECTED_RANGE range; + range.Offset = entries[i].Address; + range.Size = entries[i].Size; + range.Hash = UByteArray((const char*)entries[i].Hash, sizeof(entries[i].Hash)); + range.Type = BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT; + bgProtectedRanges.push_back(range); + } + } + else { + // Add raw data + const UINT8* data = (const UINT8*)(elementHeader + 1); + for (UINT16 i = 0; i < elementHeader->DataSize; i++) { + if (i % 32 == 0) + bootGuardInfo += UString("\n"); + bootGuardInfo += usprintf("%02X", data[i]); + } + bootGuardInfo += UString("\n"); } } else if (*currentPos == BG_BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT_TAG) { @@ -3740,7 +3783,7 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, ); // Add PubKey bootGuardInfo += usprintf("\n\nBoot Policy RSA Public Key (Exponent: %Xh):", elementHeader->KeySignature.PubKey.Exponent); - for (int i = 0; i < sizeof(elementHeader->KeySignature.PubKey.Modulus); i++) { + for (UINT16 i = 0; i < sizeof(elementHeader->KeySignature.PubKey.Modulus); i++) { if (i % 32 == 0) bootGuardInfo += UString("\n"); bootGuardInfo += usprintf("%02X", elementHeader->KeySignature.PubKey.Modulus[i]); @@ -3750,7 +3793,7 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, UINT8 hash[SHA256_DIGEST_SIZE]; sha256(&elementHeader->KeySignature.PubKey.Modulus, sizeof(elementHeader->KeySignature.PubKey.Modulus), hash); bootGuardInfo += UString("\n\nBoot Policy RSA Public Key Hash:"); - for (int i = 0; i < sizeof(hash); i++) { + for (UINT8 i = 0; i < sizeof(hash); i++) { if (i % 32 == 0) bootGuardInfo += UString("\n"); bootGuardInfo += usprintf("%02X", hash[i]); @@ -3759,13 +3802,13 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, // Add Signature bootGuardInfo += UString("\n\nBoot Policy RSA Signature:"); - for (int i = 0; i < sizeof(elementHeader->KeySignature.Signature.Signature); i++) { + for (UINT16 i = 0; i < sizeof(elementHeader->KeySignature.Signature.Signature); i++) { if (i % 32 == 0) bootGuardInfo += UString("\n"); bootGuardInfo += usprintf("%02X", elementHeader->KeySignature.Signature.Signature[i]); } } - status = findNextElement(bootPolicy, localOffset, elementOffset + elementSize, elementOffset, elementSize); + status = findNextElement(bootPolicy, elementOffset + elementSize, elementOffset, elementSize); } bootGuardInfo += UString("\n------------------------------------------------------------------------\n\n"); diff --git a/common/ffsparser.h b/common/ffsparser.h index 007bed6..8493d49 100644 --- a/common/ffsparser.h +++ b/common/ffsparser.h @@ -31,10 +31,11 @@ typedef struct BG_PROTECTED_RANGE_ UByteArray Hash; } BG_PROTECTED_RANGE; -#define BG_PROTECTED_RANGE_INTEL_BOOT_GUARD 0x01 -#define BG_PROTECTED_RANGE_VENDOR_HASH_PHOENIX 0x02 -#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_OLD 0x03 -#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_NEW 0x04 +#define BG_PROTECTED_RANGE_INTEL_BOOT_GUARD 0x01 +#define BG_PROTECTED_RANGE_VENDOR_HASH_PHOENIX 0x02 +#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_OLD 0x03 +#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_NEW 0x04 +#define BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT 0x05 class FfsParser { @@ -160,7 +161,7 @@ private: USTATUS parseIntelAcm(const UByteArray & acm, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize); USTATUS parseIntelBootGuardKeyManifest(const UByteArray & keyManifest, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize); USTATUS parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize); - USTATUS findNextElement(const UByteArray & bootPolicy, const UINT32 localOffset, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize); + USTATUS findNextElement(const UByteArray & bootPolicy, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize); #endif }; diff --git a/common/treemodel.cpp b/common/treemodel.cpp index 251d6a0..606ac09 100644 --- a/common/treemodel.cpp +++ b/common/treemodel.cpp @@ -27,7 +27,7 @@ QVariant TreeModel::data(const UModelIndex &index, int role) const return (const char*)item->data(index.column()).toLocal8Bit(); } else if (role == Qt::BackgroundRole) { - if (marking(index) > 0) { + if (markingEnabled && marking(index) > 0) { return QBrush((Qt::GlobalColor)marking(index)); } } @@ -328,6 +328,11 @@ void TreeModel::setCompressed(const UModelIndex &index, const bool compressed) emit dataChanged(index, index); } +void TreeModel::TreeModel::setMarkingEnabled(const bool enabled) +{ + markingEnabled = enabled; emit dataChanged(QModelIndex(), QModelIndex()); +} + void TreeModel::setMarking(const UModelIndex &index, const UINT8 marking) { if (!index.isValid()) diff --git a/common/treemodel.h b/common/treemodel.h index 209ca7a..89c971b 100644 --- a/common/treemodel.h +++ b/common/treemodel.h @@ -86,6 +86,7 @@ class TreeModel : public QAbstractItemModel { Q_OBJECT private: + bool markingEnabled; TreeItem *rootItem; public: @@ -93,7 +94,7 @@ public: Qt::ItemFlags flags(const UModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - TreeModel(QObject *parent = 0) : QAbstractItemModel(parent) { + TreeModel(QObject *parent = 0) : QAbstractItemModel(parent), markingEnabled(true) { rootItem = new TreeItem(0, Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), true, false); } @@ -144,6 +145,7 @@ public: void addInfo(const UModelIndex &index, const UString &info, const bool append = TRUE); void setFixed(const UModelIndex &index, const bool fixed); void setCompressed(const UModelIndex &index, const bool compressed); + void setMarkingEnabled(const bool enabled); void setMarking(const UModelIndex &index, const UINT8 marking); UINT32 offset(const UModelIndex &index) const;