Add AMI v3 protected ranges hash file support

This commit is contained in:
Nikolaj Schlej 2023-02-05 20:30:20 -08:00
parent 7a161f577a
commit 33c25e8255
3 changed files with 266 additions and 183 deletions

View file

@ -831,8 +831,11 @@ typedef struct PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V2_
typedef struct PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V3_ typedef struct PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V3_
{ {
UINT8 Hash[SHA256_HASH_SIZE]; UINT8 Hash[SHA256_HASH_SIZE];
// UINT32 Base[SOME_HARDCODED_N] UINT32 FvMainSegmentBase[3];
// UINT32 Size[SOME_HARDCODED_N]; UINT32 FvMainSegmentSize[3];
UINT32 NestedFvBase;
UINT32 NestedFvSize;
UINT8 Reserved[48];
} PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V3; } PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V3;
// //

View file

@ -3468,15 +3468,13 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
// QByteArray (Qt builds) supports obtaining data from invalid offsets in QByteArray, // QByteArray (Qt builds) supports obtaining data from invalid offsets in QByteArray,
// so mid() here doesn't throw anything for UEFITool, just returns ranges with all zeroes // so mid() here doesn't throw anything for UEFITool, just returns ranges with all zeroes
// UByteArray (non-Qt builds) throws an exception that needs to be caught every time or the tools will crash. // UByteArray (non-Qt builds) throws an exception that needs to be caught every time or the tools will crash.
// TODO: add sanity checks everythere so non-Qt UByteArray stuff don't need to throw
// Calculate digest for BG-protected ranges // Calculate digest for BG-protected ranges
UByteArray protectedParts; UByteArray protectedParts;
bool bgProtectedRangeFound = false; bool bgProtectedRangeFound = false;
try { try {
for (UINT32 i = 0; i < (UINT32)protectedRanges.size(); i++) { for (UINT32 i = 0; i < (UINT32)protectedRanges.size(); i++) {
if (protectedRanges[i].Type == PROTECTED_RANGE_INTEL_BOOT_GUARD_IBB if (protectedRanges[i].Type == PROTECTED_RANGE_INTEL_BOOT_GUARD_IBB) {
&& protectedRanges[i].Size > 0) {
bgProtectedRangeFound = true; bgProtectedRangeFound = true;
if ((UINT64)protectedRanges[i].Offset >= addressDiff) { if ((UINT64)protectedRanges[i].Offset >= addressDiff) {
protectedRanges[i].Offset -= (UINT32)addressDiff; protectedRanges[i].Offset -= (UINT32)addressDiff;
@ -3536,39 +3534,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
// Calculate digests for vendor-protected ranges // Calculate digests for vendor-protected ranges
for (UINT32 i = 0; i < (UINT32)protectedRanges.size(); i++) { for (UINT32 i = 0; i < (UINT32)protectedRanges.size(); i++) {
if (protectedRanges[i].Type == PROTECTED_RANGE_VENDOR_HASH_AMI_V1) { if (protectedRanges[i].Type == PROTECTED_RANGE_INTEL_BOOT_GUARD_POST_IBB) {
if (!dxeCore.isValid()) {
msg(usprintf("%s: can't determine DXE volume offset, old AMI protected range hash can't be checked", __FUNCTION__), index);
}
else {
// Offset will be determined as the offset of root volume with first DXE core
UModelIndex dxeRootVolumeIndex = model->findLastParentOfType(dxeCore, Types::Volume);
if (!dxeRootVolumeIndex.isValid()) {
msg(usprintf("%s: can't determine DXE volume offset, old AMI protected range hash can't be checked", __FUNCTION__), index);
}
else {
try {
protectedRanges[i].Offset = model->base(dxeRootVolumeIndex);
protectedParts = openedImage.mid(protectedRanges[i].Offset, protectedRanges[i].Size);
UByteArray digest(SHA256_HASH_SIZE, '\x00');
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
if (digest != protectedRanges[i].Hash) {
msg(usprintf("%s: old AMI protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", __FUNCTION__,
protectedRanges[i].Offset, protectedRanges[i].Offset + protectedRanges[i].Size),
model->findByBase(protectedRanges[i].Offset));
}
markProtectedRangeRecursive(index, protectedRanges[i]);
}
catch(...) {
// Do nothing, this range is likely not found in the image
}
}
}
}
else if (protectedRanges[i].Type == PROTECTED_RANGE_INTEL_BOOT_GUARD_POST_IBB) {
if (!dxeCore.isValid()) { if (!dxeCore.isValid()) {
msg(usprintf("%s: can't determine DXE volume offset, post-IBB protected range hash can't be checked", __FUNCTION__), index); msg(usprintf("%s: can't determine DXE volume offset, post-IBB protected range hash can't be checked", __FUNCTION__), index);
} }
@ -3627,6 +3593,38 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
} }
} }
} }
else if (protectedRanges[i].Type == PROTECTED_RANGE_VENDOR_HASH_AMI_V1) {
if (!dxeCore.isValid()) {
msg(usprintf("%s: can't determine DXE volume offset, AMI v1 protected range hash can't be checked", __FUNCTION__), index);
}
else {
// Offset will be determined as the offset of root volume with first DXE core
UModelIndex dxeRootVolumeIndex = model->findLastParentOfType(dxeCore, Types::Volume);
if (!dxeRootVolumeIndex.isValid()) {
msg(usprintf("%s: can't determine DXE volume offset, AMI v1 protected range hash can't be checked", __FUNCTION__), index);
}
else {
try {
protectedRanges[i].Offset = model->base(dxeRootVolumeIndex);
protectedParts = openedImage.mid(protectedRanges[i].Offset, protectedRanges[i].Size);
UByteArray digest(SHA256_HASH_SIZE, '\x00');
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
if (digest != protectedRanges[i].Hash) {
msg(usprintf("%s: AMI v1 protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", __FUNCTION__,
protectedRanges[i].Offset, protectedRanges[i].Offset + protectedRanges[i].Size),
model->findByBase(protectedRanges[i].Offset));
}
markProtectedRangeRecursive(index, protectedRanges[i]);
}
catch (...) {
// Do nothing, this range is likely not found in the image
}
}
}
}
else if (protectedRanges[i].Type == PROTECTED_RANGE_VENDOR_HASH_AMI_V2) { else if (protectedRanges[i].Type == PROTECTED_RANGE_VENDOR_HASH_AMI_V2) {
try { try {
protectedRanges[i].Offset -= (UINT32)addressDiff; protectedRanges[i].Offset -= (UINT32)addressDiff;
@ -3636,7 +3634,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
sha256(protectedParts.constData(), protectedParts.size(), digest.data()); sha256(protectedParts.constData(), protectedParts.size(), digest.data());
if (digest != protectedRanges[i].Hash) { if (digest != protectedRanges[i].Hash) {
msg(usprintf("%s: AMI protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", __FUNCTION__, msg(usprintf("%s: AMI v2 protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", __FUNCTION__,
protectedRanges[i].Offset, protectedRanges[i].Offset + protectedRanges[i].Size), protectedRanges[i].Offset, protectedRanges[i].Offset + protectedRanges[i].Size),
model->findByBase(protectedRanges[i].Offset)); model->findByBase(protectedRanges[i].Offset));
} }
@ -3647,9 +3645,51 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
// Do nothing, this range is likely not found in the image // Do nothing, this range is likely not found in the image
} }
} }
else if (protectedRanges[i].Type == PROTECTED_RANGE_VENDOR_HASH_PHOENIX else if (protectedRanges[i].Type == PROTECTED_RANGE_VENDOR_HASH_AMI_V3) {
&& protectedRanges[i].Size != 0 && protectedRanges[i].Size != 0xFFFFFFFF try {
&& protectedRanges[i].Offset != 0xFFFFFFFF) { protectedRanges[i].Offset -= (UINT32)addressDiff;
protectedParts = openedImage.mid(protectedRanges[i].Offset, protectedRanges[i].Size);
markProtectedRangeRecursive(index, protectedRanges[i]);
// Process second range
if (i + 1 < (UINT32)protectedRanges.size() && protectedRanges[i + 1].Type == PROTECTED_RANGE_VENDOR_HASH_AMI_V3) {
protectedRanges[i + 1].Offset -= (UINT32)addressDiff;
protectedParts += openedImage.mid(protectedRanges[i + 1].Offset, protectedRanges[i + 1].Size);
markProtectedRangeRecursive(index, protectedRanges[i + 1]);
// Process third range
if (i + 2 < (UINT32)protectedRanges.size() && protectedRanges[i + 2].Type == PROTECTED_RANGE_VENDOR_HASH_AMI_V3) {
protectedRanges[i + 2].Offset -= (UINT32)addressDiff;
protectedParts += openedImage.mid(protectedRanges[i + 2].Offset, protectedRanges[i + 2].Size);
markProtectedRangeRecursive(index, protectedRanges[i + 2]);
// Process fourth range
if (i + 3 < (UINT32)protectedRanges.size() && protectedRanges[i + 3].Type == PROTECTED_RANGE_VENDOR_HASH_AMI_V3) {
protectedRanges[i + 3].Offset -= (UINT32)addressDiff;
protectedParts += openedImage.mid(protectedRanges[i + 3].Offset, protectedRanges[i + 3].Size);
markProtectedRangeRecursive(index, protectedRanges[i + 3]);
i += 3; // Skip 3 already processed ranges
}
else {
i += 2; // Skip 2 already processed ranges
}
}
else {
i += 1; // Skip 1 already processed range
}
}
UByteArray digest(SHA256_HASH_SIZE, '\x00');
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
if (digest != protectedRanges[i].Hash) {
msg(usprintf("%s: AMI v3 protected ranges hash mismatch, opened image may refuse to boot", __FUNCTION__));
}
}
catch (...) {
// Do nothing, this range is likely not found in the image
}
}
else if (protectedRanges[i].Type == PROTECTED_RANGE_VENDOR_HASH_PHOENIX) {
try { try {
protectedRanges[i].Offset += (UINT32)protectedRegionsBase; protectedRanges[i].Offset += (UINT32)protectedRegionsBase;
protectedParts = openedImage.mid(protectedRanges[i].Offset, protectedRanges[i].Size); protectedParts = openedImage.mid(protectedRanges[i].Offset, protectedRanges[i].Size);
@ -3669,9 +3709,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
// Do nothing, this range is likely not found in the image // Do nothing, this range is likely not found in the image
} }
} }
else if (protectedRanges[i].Type == PROTECTED_RANGE_VENDOR_HASH_MICROSOFT_PMDA else if (protectedRanges[i].Type == PROTECTED_RANGE_VENDOR_HASH_MICROSOFT_PMDA) {
&& protectedRanges[i].Size != 0 && protectedRanges[i].Size != 0xFFFFFFFF
&& protectedRanges[i].Offset != 0 && protectedRanges[i].Offset != 0xFFFFFFFF) {
try { try {
protectedRanges[i].Offset -= (UINT32)addressDiff; protectedRanges[i].Offset -= (UINT32)addressDiff;
protectedParts = openedImage.mid(protectedRanges[i].Offset, protectedRanges[i].Size); protectedParts = openedImage.mid(protectedRanges[i].Offset, protectedRanges[i].Size);
@ -3766,136 +3804,170 @@ USTATUS FfsParser::parseVendorHashFile(const UByteArray & fileGuid, const UModel
return U_INVALID_PARAMETER; return U_INVALID_PARAMETER;
} }
const UByteArray& body = model->body(index);
UINT32 size = (UINT32)body.size();
if (fileGuid == PROTECTED_RANGE_VENDOR_HASH_FILE_GUID_PHOENIX) { if (fileGuid == PROTECTED_RANGE_VENDOR_HASH_FILE_GUID_PHOENIX) {
const UByteArray &body = model->body(index); if (size < sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_PHOENIX)) {
UINT32 size = (UINT32)body.size(); msg(usprintf("%s: unknown or corrupted Phoenix protected ranges hash file", __FUNCTION__), index);
// File too small to have even a signature
if (size < sizeof(UINT64)) {
msg(usprintf("%s: unknown or corrupted Phoenix hash file found", __FUNCTION__), index);
model->setText(index, UString("Phoenix hash file"));
return U_INVALID_FILE;
} }
else {
const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_PHOENIX* header = (const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_PHOENIX*)body.constData(); const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_PHOENIX* header = (const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_PHOENIX*)body.constData();
if (header->Signature == BG_VENDOR_HASH_FILE_SIGNATURE_PHOENIX) { if (header->Signature == BG_VENDOR_HASH_FILE_SIGNATURE_PHOENIX) {
if (size < sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_PHOENIX) || if (size < sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_PHOENIX) + header->NumEntries * sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY)) {
size < sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_PHOENIX) + header->NumEntries * sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY)) { msg(usprintf("%s: unknown or corrupted Phoenix protected ranges hash file", __FUNCTION__), index);
msg(usprintf("%s: unknown or corrupted Phoenix hash file found", __FUNCTION__), index);
model->setText(index, UString("Phoenix hash file"));
return U_INVALID_FILE;
}
if (header->NumEntries > 0) {
bool protectedRangesFound = false;
for (UINT32 i = 0; i < header->NumEntries; i++) {
protectedRangesFound = true;
const PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY* entry = (const PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY*)(header + 1) + i;
PROTECTED_RANGE range = {};
range.Offset = entry->Base;
range.Size = entry->Size;
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash, sizeof(entry->Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_PHOENIX;
protectedRanges.push_back(range);
} }
else {
if (protectedRangesFound) { if (header->NumEntries > 0) {
securityInfo += usprintf("Phoenix hash file found at base %08Xh\nProtected ranges:\n", model->base(index)); bool protectedRangesFound = false;
for (UINT32 i = 0; i < header->NumEntries; i++) { for (UINT32 i = 0; i < header->NumEntries; i++) {
const PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY* entry = (const PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY*)(header + 1) + i; const PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY* entry = (const PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY*)(header + 1) + i;
securityInfo += usprintf("RelativeOffset: %08Xh Size: %Xh\nHash: ", entry->Base, entry->Size); if (entry->Base != 0xFFFFFFFF && entry->Size != 0 && entry->Size != 0xFFFFFFFF) {
for (UINT8 j = 0; j < sizeof(entry->Hash); j++) { protectedRangesFound = true;
securityInfo += usprintf("%02X", entry->Hash[j]); PROTECTED_RANGE range = {};
range.Offset = entry->Base;
range.Size = entry->Size;
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash, sizeof(entry->Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_PHOENIX;
protectedRanges.push_back(range);
}
}
if (protectedRangesFound) {
securityInfo += usprintf("Phoenix hash file found at base %08Xh\nProtected ranges:\n", model->base(index));
for (UINT32 i = 0; i < header->NumEntries; i++) {
const PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY* entry = (const PROTECTED_RANGE_VENDOR_HASH_FILE_ENTRY*)(header + 1) + i;
securityInfo += usprintf("RelativeOffset: %08Xh Size: %Xh\nHash: ", entry->Base, entry->Size);
for (UINT8 j = 0; j < sizeof(entry->Hash); j++) {
securityInfo += usprintf("%02X", entry->Hash[j]);
}
securityInfo += "\n";
}
} }
securityInfo += "\n";
} }
securityInfo += "\n";
} }
msg(usprintf("%s: Phoenix hash file found", __FUNCTION__), index);
} }
else {
msg(usprintf("%s: empty Phoenix hash file found", __FUNCTION__), index);
}
model->setText(index, UString("Phoenix hash file"));
} }
model->setText(index, UString("Phoenix protected ranges hash file"));
} }
else if (fileGuid == PROTECTED_RANGE_VENDOR_HASH_FILE_GUID_AMI) { else if (fileGuid == PROTECTED_RANGE_VENDOR_HASH_FILE_GUID_AMI) {
UModelIndex fileIndex = model->parent(index); UModelIndex fileIndex = model->parent(index);
const UByteArray &body = model->body(index); if (size == sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V1)) {
UINT32 size = (UINT32)body.size(); securityInfo += usprintf("AMI protected ranges hash file v1 found at base %08Xh\nProtected range:\n", model->base(fileIndex));
if (size != (UINT32)body.count('\xFF')) { const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V1* entry = (const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V1*)(body.constData());
if (size == sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V2)) { securityInfo += usprintf("Size: %Xh\nHash (SHA256): ", entry->Size);
const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V2* entry = (const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V2*)(body.constData()); for (UINT8 i = 0; i < sizeof(entry->Hash); i++) {
securityInfo += usprintf("%02X", entry->Hash[i]);
securityInfo += usprintf("AMI hash file v2 found at base %08Xh\nProtected ranges:", model->base(fileIndex));
securityInfo += usprintf("\nAddress: %08Xh, Size: %Xh\nHash (SHA256): ", entry->Hash0.Base, entry->Hash0.Size);
for (UINT8 j = 0; j < sizeof(entry->Hash0.Hash); j++) {
securityInfo += usprintf("%02X", entry->Hash0.Hash[j]);
}
securityInfo += usprintf("\nAddress: %08Xh, Size: %Xh\nHash (SHA256): ", entry->Hash1.Base, entry->Hash1.Size);
for (UINT8 j = 0; j < sizeof(entry->Hash1.Hash); j++) {
securityInfo += usprintf("%02X", entry->Hash1.Hash[j]);
}
securityInfo += "\n";
if (entry->Hash0.Base != 0 && entry->Hash0.Size != 0
&& entry->Hash0.Base != 0xFFFFFFFF && entry->Hash0.Size != 0xFFFFFFFF) {
PROTECTED_RANGE range = {};
range.Offset = entry->Hash0.Base;
range.Size = entry->Hash0.Size;
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash0.Hash, sizeof(entry->Hash0.Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V2;
protectedRanges.push_back(range);
}
if (entry->Hash1.Base != 0 && entry->Hash1.Size != 0
&& entry->Hash1.Base != 0xFFFFFFFF && entry->Hash1.Size != 0xFFFFFFFF) {
PROTECTED_RANGE range = {};
range.Offset = entry->Hash1.Base;
range.Size = entry->Hash1.Size;
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash1.Hash, sizeof(entry->Hash1.Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V2;
protectedRanges.push_back(range);
}
msg(usprintf("%s: AMI hash file v2 found", __FUNCTION__), fileIndex);
} }
else if (size == sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V1)) { securityInfo += "\n";
securityInfo += usprintf("AMI hash file v1 found at base %08Xh\nProtected range:\n", model->base(fileIndex));
const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V1* entry = (const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V1*)(body.constData());
securityInfo += usprintf("Size: %Xh\nHash (SHA256): ", entry->Size);
for (UINT8 i = 0; i < sizeof(entry->Hash); i++) {
securityInfo += usprintf("%02X", entry->Hash[i]);
}
securityInfo += "\n\n";
if (entry->Size != 0 && entry->Size != 0xFFFFFFFF) { if (entry->Size != 0 && entry->Size != 0xFFFFFFFF) {
PROTECTED_RANGE range = {}; PROTECTED_RANGE range = {};
range.Offset = 0; range.Offset = 0;
range.Size = entry->Size; range.Size = entry->Size;
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256; range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash, sizeof(entry->Hash)); range.Hash = UByteArray((const char*)entry->Hash, sizeof(entry->Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V1; range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V1;
protectedRanges.push_back(range); protectedRanges.push_back(range);
} }
msg(usprintf("%s: AMI hash file v1 found", __FUNCTION__), fileIndex); model->setText(fileIndex, UString("AMI v1 protected ranges hash file"));
}
else if (size == sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V2)) {
const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V2* entry = (const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V2*)(body.constData());
securityInfo += usprintf("AMI v2 protected ranges hash file found at base %08Xh\nProtected ranges:", model->base(fileIndex));
securityInfo += usprintf("\nAddress: %08Xh, Size: %Xh\nHash (SHA256): ", entry->Hash0.Base, entry->Hash0.Size);
for (UINT8 j = 0; j < sizeof(entry->Hash0.Hash); j++) {
securityInfo += usprintf("%02X", entry->Hash0.Hash[j]);
} }
else { securityInfo += usprintf("\nAddress: %08Xh, Size: %Xh\nHash (SHA256): ", entry->Hash1.Base, entry->Hash1.Size);
msg(usprintf("%s: unknown or corrupted AMI hash file found", __FUNCTION__), index); for (UINT8 j = 0; j < sizeof(entry->Hash1.Hash); j++) {
securityInfo += usprintf("%02X", entry->Hash1.Hash[j]);
} }
securityInfo += "\n";
if (entry->Hash0.Base != 0xFFFFFFFF && entry->Hash0.Size != 0 && entry->Hash0.Size != 0xFFFFFFFF) {
PROTECTED_RANGE range = {};
range.Offset = entry->Hash0.Base;
range.Size = entry->Hash0.Size;
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash0.Hash, sizeof(entry->Hash0.Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V2;
protectedRanges.push_back(range);
}
if (entry->Hash1.Base != 0xFFFFFFFF && entry->Hash1.Size != 0 && entry->Hash1.Size != 0xFFFFFFFF) {
PROTECTED_RANGE range = {};
range.Offset = entry->Hash1.Base;
range.Size = entry->Hash1.Size;
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash1.Hash, sizeof(entry->Hash1.Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V2;
protectedRanges.push_back(range);
}
model->setText(fileIndex, UString("AMI v2 protected ranges hash file"));
}
else if (size == sizeof(PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V3)) {
const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V3* entry = (const PROTECTED_RANGE_VENDOR_HASH_FILE_HEADER_AMI_V3*)(body.constData());
securityInfo += usprintf("AMI v3 protected ranges hash file found at base %08Xh\nProtected ranges:", model->base(fileIndex));
securityInfo += usprintf("\nFvBaseSegment 0 Address: %08Xh, Size: %Xh", entry->FvMainSegmentBase[0], entry->FvMainSegmentSize[0]);
securityInfo += usprintf("\nFvBaseSegment 1 Address: %08Xh, Size: %Xh", entry->FvMainSegmentBase[1], entry->FvMainSegmentSize[1]);
securityInfo += usprintf("\nFvBaseSegment 2 Address: %08Xh, Size: %Xh", entry->FvMainSegmentBase[2], entry->FvMainSegmentSize[2]);
securityInfo += usprintf("\nNestedFvBase Address: %08Xh, Size: %Xh", entry->NestedFvBase, entry->NestedFvSize);
securityInfo += usprintf("\nHash (SHA256): ");
for (UINT8 j = 0; j < sizeof(entry->Hash); j++) {
securityInfo += usprintf("%02X", entry->Hash[j]);
}
securityInfo += "\n";
if (entry->FvMainSegmentBase[0] != 0xFFFFFFFF && entry->FvMainSegmentSize[0] != 0 && entry->FvMainSegmentSize[0] != 0xFFFFFFFF) {
PROTECTED_RANGE range = {};
range.Offset = entry->FvMainSegmentBase[0];
range.Size = entry->FvMainSegmentSize[0];
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash, sizeof(entry->Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V3;
protectedRanges.push_back(range);
}
if (entry->FvMainSegmentBase[1] != 0xFFFFFFFF && entry->FvMainSegmentSize[1] != 0 && entry->FvMainSegmentSize[1] != 0xFFFFFFFF) {
PROTECTED_RANGE range = {};
range.Offset = entry->FvMainSegmentBase[1];
range.Size = entry->FvMainSegmentSize[1];
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash, sizeof(entry->Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V3;
protectedRanges.push_back(range);
}
if (entry->FvMainSegmentBase[2] != 0xFFFFFFFF && entry->FvMainSegmentSize[2] != 0 && entry->FvMainSegmentSize[2] != 0xFFFFFFFF) {
PROTECTED_RANGE range = {};
range.Offset = entry->FvMainSegmentBase[2];
range.Size = entry->FvMainSegmentSize[2];
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash, sizeof(entry->Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V3;
protectedRanges.push_back(range);
}
if (entry->NestedFvBase != 0xFFFFFFFF && entry->NestedFvSize != 0 && entry->NestedFvSize != 0xFFFFFFFF) {
PROTECTED_RANGE range = {};
range.Offset = entry->NestedFvBase;
range.Size = entry->NestedFvSize;
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
range.Hash = UByteArray((const char*)entry->Hash, sizeof(entry->Hash));
range.Type = PROTECTED_RANGE_VENDOR_HASH_AMI_V3;
protectedRanges.push_back(range);
}
model->setText(fileIndex, UString("AMI v3 protected ranges hash file"));
} }
else { else {
msg(usprintf("%s: empty AMI hash file found", __FUNCTION__), fileIndex); msg(usprintf("%s: unknown or corrupted AMI protected ranges hash file", __FUNCTION__), fileIndex);
} }
model->setText(fileIndex, UString("AMI hash file"));
} }
return U_SUCCESS; return U_SUCCESS;

View file

@ -703,7 +703,7 @@ USTATUS FitParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic
for (intel_acbp_v1_t::acbp_element_t* element : *elements) { for (intel_acbp_v1_t::acbp_element_t* element : *elements) {
const intel_acbp_v1_t::common_header_t* element_header = element->header(); const intel_acbp_v1_t::common_header_t* element_header = element->header();
UINT64 structure_id = element_header->structure_id(); UINT64 structure_id = (UINT64) element_header->structure_id();
const char* structure_id_bytes = (const char*)&structure_id; const char* structure_id_bytes = (const char*)&structure_id;
bpInfo += usprintf("StructureId: '%c%c%c%c%c%c%c%c'\n" bpInfo += usprintf("StructureId: '%c%c%c%c%c%c%c%c'\n"
@ -788,7 +788,8 @@ USTATUS FitParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic
current_segment->base(), current_segment->base(),
current_segment->size()); current_segment->size());
if (current_segment->flags() == intel_acbp_v1_t::IBB_SEGMENT_TYPE_IBB) { if (current_segment->flags() == intel_acbp_v1_t::IBB_SEGMENT_TYPE_IBB
&& current_segment->base() != 0xFFFFFFFF && current_segment->size() != 0 && current_segment->size() != 0xFFFFFFFF) {
PROTECTED_RANGE range = {}; PROTECTED_RANGE range = {};
range.Offset = current_segment->base(); range.Offset = current_segment->base();
range.Size = current_segment->size(); range.Size = current_segment->size();
@ -833,13 +834,15 @@ USTATUS FitParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic
bpInfo += "\n"; bpInfo += "\n";
// Add protected range // Add protected range
PROTECTED_RANGE range = {}; if (current_element->base() != 0xFFFFFFFF && current_element->size() != 0 && current_element->size() != 0xFFFFFFFF) {
range.Offset = current_element->base(); PROTECTED_RANGE range = {};
range.Size = current_element->size(); range.Offset = current_element->base();
range.Type = PROTECTED_RANGE_VENDOR_HASH_MICROSOFT_PMDA; range.Size = current_element->size();
range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256; range.Type = PROTECTED_RANGE_VENDOR_HASH_MICROSOFT_PMDA;
range.Hash = UByteArray(current_element->hash().data(), current_element->hash().size()); range.AlgorithmId = TCG_HASH_ALGORITHM_ID_SHA256;
ffsParser->protectedRanges.push_back(range); range.Hash = UByteArray(current_element->hash().data(), current_element->hash().size());
ffsParser->protectedRanges.push_back(range);
}
} }
} }
// v2 entries // v2 entries
@ -860,13 +863,15 @@ USTATUS FitParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic
bpInfo += "\n"; bpInfo += "\n";
// Add protected range // Add protected range
PROTECTED_RANGE range = {}; if (current_element->base() != 0xFFFFFFFF && current_element->size() != 0 && current_element->size() != 0xFFFFFFFF) {
range.Offset = current_element->base(); PROTECTED_RANGE range = {};
range.Size = current_element->size(); range.Offset = current_element->base();
range.Type = PROTECTED_RANGE_VENDOR_HASH_MICROSOFT_PMDA; range.Size = current_element->size();
range.AlgorithmId = current_element->hash()->hash_algorithm_id(); range.Type = PROTECTED_RANGE_VENDOR_HASH_MICROSOFT_PMDA;
range.Hash = UByteArray(current_element->hash()->hash().data(), current_element->hash()->hash().size()); range.AlgorithmId = current_element->hash()->hash_algorithm_id();
ffsParser->protectedRanges.push_back(range); range.Hash = UByteArray(current_element->hash()->hash().data(), current_element->hash()->hash().size());
ffsParser->protectedRanges.push_back(range);
}
} }
} }
} }
@ -1099,7 +1104,8 @@ USTATUS FitParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic
current_segment->base(), current_segment->base(),
current_segment->size()); current_segment->size());
if (current_segment->flags() == intel_acbp_v2_t::IBB_SEGMENT_TYPE_IBB) { if (current_segment->flags() == intel_acbp_v2_t::IBB_SEGMENT_TYPE_IBB
&& current_segment->base() != 0xFFFFFFFF && current_segment->size() != 0 && current_segment->size() != 0xFFFFFFFF) {
PROTECTED_RANGE range = {}; PROTECTED_RANGE range = {};
range.Offset = current_segment->base(); range.Offset = current_segment->base();
range.Size =current_segment->size(); range.Size =current_segment->size();
@ -1151,13 +1157,15 @@ USTATUS FitParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic
bpInfo += "\n"; bpInfo += "\n";
// Add protected range // Add protected range
PROTECTED_RANGE range = {}; if (current_entry->base() != 0xFFFFFFFF && current_entry->size() != 0 && current_entry->size() != 0xFFFFFFFF) {
range.Offset = current_entry->base(); PROTECTED_RANGE range = {};
range.Size = current_entry->size(); range.Offset = current_entry->base();
range.Type = PROTECTED_RANGE_VENDOR_HASH_MICROSOFT_PMDA; range.Size = current_entry->size();
range.AlgorithmId = current_entry->hash()->hash_algorithm_id(); range.Type = PROTECTED_RANGE_VENDOR_HASH_MICROSOFT_PMDA;
range.Hash = UByteArray(current_entry->hash()->hash().data(), current_entry->hash()->hash().size()); range.AlgorithmId = current_entry->hash()->hash_algorithm_id();
ffsParser->protectedRanges.push_back(range); range.Hash = UByteArray(current_entry->hash()->hash().data(), current_entry->hash()->hash().size());
ffsParser->protectedRanges.push_back(range);
}
} }
} }
} }