mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-04 13:23:26 +01:00
237 lines
6.1 KiB
C
237 lines
6.1 KiB
C
/** @file
|
|
|
|
Blob verifier library that uses SEV hashes table. The hashes table holds the
|
|
allowed hashes of the kernel, initrd, and cmdline blobs.
|
|
|
|
Copyright (C) 2021, IBM Corporation
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
|
|
|
#include <Library/BaseCryptLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BlobVerifierLib.h>
|
|
|
|
/**
|
|
The SEV Hashes table must be in encrypted memory and has the table
|
|
and its entries described by
|
|
|
|
<GUID>|UINT16 <len>|<data>
|
|
|
|
With the whole table GUID being 9438d606-4f22-4cc9-b479-a793d411fd21
|
|
|
|
The current possible table entries are for the kernel, the initrd
|
|
and the cmdline:
|
|
|
|
4de79437-abd2-427f-b835-d5b172d2045b kernel
|
|
44baf731-3a2f-4bd7-9af1-41e29169781d initrd
|
|
97d02dd8-bd20-4c94-aa78-e7714d36ab2a cmdline
|
|
|
|
The size of the entry is used to identify the hash, but the
|
|
expectation is that it will be 32 bytes of SHA-256.
|
|
**/
|
|
|
|
#define SEV_HASH_TABLE_GUID \
|
|
(GUID) { 0x9438d606, 0x4f22, 0x4cc9, { 0xb4, 0x79, 0xa7, 0x93, 0xd4, 0x11, 0xfd, 0x21 } }
|
|
#define SEV_KERNEL_HASH_GUID \
|
|
(GUID) { 0x4de79437, 0xabd2, 0x427f, { 0xb8, 0x35, 0xd5, 0xb1, 0x72, 0xd2, 0x04, 0x5b } }
|
|
#define SEV_INITRD_HASH_GUID \
|
|
(GUID) { 0x44baf731, 0x3a2f, 0x4bd7, { 0x9a, 0xf1, 0x41, 0xe2, 0x91, 0x69, 0x78, 0x1d } }
|
|
#define SEV_CMDLINE_HASH_GUID \
|
|
(GUID) { 0x97d02dd8, 0xbd20, 0x4c94, { 0xaa, 0x78, 0xe7, 0x71, 0x4d, 0x36, 0xab, 0x2a } }
|
|
|
|
STATIC CONST EFI_GUID mSevKernelHashGuid = SEV_KERNEL_HASH_GUID;
|
|
STATIC CONST EFI_GUID mSevInitrdHashGuid = SEV_INITRD_HASH_GUID;
|
|
STATIC CONST EFI_GUID mSevCmdlineHashGuid = SEV_CMDLINE_HASH_GUID;
|
|
|
|
#pragma pack (1)
|
|
typedef struct {
|
|
GUID Guid;
|
|
UINT16 Len;
|
|
UINT8 Data[];
|
|
} HASH_TABLE;
|
|
#pragma pack ()
|
|
|
|
STATIC HASH_TABLE *mHashesTable;
|
|
STATIC UINT16 mHashesTableSize;
|
|
|
|
STATIC
|
|
CONST GUID *
|
|
FindBlobEntryGuid (
|
|
IN CONST CHAR16 *BlobName
|
|
)
|
|
{
|
|
if (StrCmp (BlobName, L"kernel") == 0) {
|
|
return &mSevKernelHashGuid;
|
|
} else if (StrCmp (BlobName, L"initrd") == 0) {
|
|
return &mSevInitrdHashGuid;
|
|
} else if (StrCmp (BlobName, L"cmdline") == 0) {
|
|
return &mSevCmdlineHashGuid;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Verify blob from an external source.
|
|
|
|
@param[in] BlobName The name of the blob
|
|
@param[in] Buf The data of the blob
|
|
@param[in] BufSize The size of the blob in bytes
|
|
|
|
@retval EFI_SUCCESS The blob was verified successfully.
|
|
@retval EFI_ACCESS_DENIED The blob could not be verified, and therefore
|
|
should be considered non-secure.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
VerifyBlob (
|
|
IN CONST CHAR16 *BlobName,
|
|
IN CONST VOID *Buf,
|
|
IN UINT32 BufSize
|
|
)
|
|
{
|
|
CONST GUID *Guid;
|
|
INT32 Remaining;
|
|
HASH_TABLE *Entry;
|
|
|
|
if ((mHashesTable == NULL) || (mHashesTableSize == 0)) {
|
|
DEBUG ((
|
|
DEBUG_ERROR,
|
|
"%a: Verifier called but no hashes table discoverd in MEMFD\n",
|
|
__func__
|
|
));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
Guid = FindBlobEntryGuid (BlobName);
|
|
if (Guid == NULL) {
|
|
DEBUG ((
|
|
DEBUG_ERROR,
|
|
"%a: Unknown blob name \"%s\"\n",
|
|
__func__,
|
|
BlobName
|
|
));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
//
|
|
// Remaining is INT32 to catch underflow in case Entry->Len has a
|
|
// very high UINT16 value
|
|
//
|
|
for (Entry = mHashesTable, Remaining = mHashesTableSize;
|
|
Remaining >= sizeof *Entry && Remaining >= Entry->Len;
|
|
Remaining -= Entry->Len,
|
|
Entry = (HASH_TABLE *)((UINT8 *)Entry + Entry->Len))
|
|
{
|
|
UINTN EntrySize;
|
|
EFI_STATUS Status;
|
|
UINT8 Hash[SHA256_DIGEST_SIZE];
|
|
|
|
if (!CompareGuid (&Entry->Guid, Guid)) {
|
|
continue;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a: Found GUID %g in table\n", __func__, Guid));
|
|
|
|
EntrySize = Entry->Len - sizeof Entry->Guid - sizeof Entry->Len;
|
|
if (EntrySize != SHA256_DIGEST_SIZE) {
|
|
DEBUG ((
|
|
DEBUG_ERROR,
|
|
"%a: Hash has the wrong size %d != %d\n",
|
|
__func__,
|
|
EntrySize,
|
|
SHA256_DIGEST_SIZE
|
|
));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
//
|
|
// Calculate the buffer's hash and verify that it is identical to the
|
|
// expected hash table entry
|
|
//
|
|
Sha256HashAll (Buf, BufSize, Hash);
|
|
|
|
if (CompareMem (Entry->Data, Hash, EntrySize) == 0) {
|
|
Status = EFI_SUCCESS;
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"%a: Hash comparison succeeded for \"%s\"\n",
|
|
__func__,
|
|
BlobName
|
|
));
|
|
} else {
|
|
Status = EFI_ACCESS_DENIED;
|
|
DEBUG ((
|
|
DEBUG_ERROR,
|
|
"%a: Hash comparison failed for \"%s\"\n",
|
|
__func__,
|
|
BlobName
|
|
));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
DEBUG ((
|
|
DEBUG_ERROR,
|
|
"%a: Hash GUID %g not found in table\n",
|
|
__func__,
|
|
Guid
|
|
));
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
/**
|
|
Locate the SEV hashes table.
|
|
|
|
This function always returns success, even if the table can't be found. The
|
|
subsequent VerifyBlob calls will fail if no table was found.
|
|
|
|
@retval RETURN_SUCCESS The hashes table is set up correctly, or there is no
|
|
hashes table
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
BlobVerifierLibSevHashesConstructor (
|
|
VOID
|
|
)
|
|
{
|
|
HASH_TABLE *Ptr;
|
|
UINT32 Size;
|
|
|
|
mHashesTable = NULL;
|
|
mHashesTableSize = 0;
|
|
|
|
Ptr = (void *)(UINTN)FixedPcdGet64 (PcdQemuHashTableBase);
|
|
Size = FixedPcdGet32 (PcdQemuHashTableSize);
|
|
|
|
if ((Ptr == NULL) || (Size < sizeof *Ptr) ||
|
|
!CompareGuid (&Ptr->Guid, &SEV_HASH_TABLE_GUID) ||
|
|
(Ptr->Len < sizeof *Ptr) || (Ptr->Len > Size))
|
|
{
|
|
return RETURN_SUCCESS;
|
|
}
|
|
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"%a: Found injected hashes table in secure location\n",
|
|
__func__
|
|
));
|
|
|
|
mHashesTable = (HASH_TABLE *)Ptr->Data;
|
|
mHashesTableSize = Ptr->Len - sizeof Ptr->Guid - sizeof Ptr->Len;
|
|
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"%a: mHashesTable=0x%p, Size=%u\n",
|
|
__func__,
|
|
mHashesTable,
|
|
mHashesTableSize
|
|
));
|
|
|
|
return RETURN_SUCCESS;
|
|
}
|