summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierLibSevHashes.inf37
-rw-r--r--OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c202
-rw-r--r--OvmfPkg/OvmfPkg.ci.yaml1
3 files changed, 240 insertions, 0 deletions
diff --git a/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierLibSevHashes.inf b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierLibSevHashes.inf
new file mode 100644
index 0000000000..76ca0b8154
--- /dev/null
+++ b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierLibSevHashes.inf
@@ -0,0 +1,37 @@
+## @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 Corp
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = BlobVerifierLibSevHashes
+ FILE_GUID = 59e713b5-eff3-46a7-8d8b-46f4c004ad7b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BlobVerifierLib
+ CONSTRUCTOR = BlobVerifierLibSevHashesConstructor
+
+[Sources]
+ BlobVerifierSevHashes.c
+
+[Packages]
+ CryptoPkg/CryptoPkg.dec
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseCryptLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+
+[FixedPcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize
diff --git a/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c
new file mode 100644
index 0000000000..b9054879b0
--- /dev/null
+++ b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c
@@ -0,0 +1,202 @@
+/** @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",
+ __FUNCTION__));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Guid = FindBlobEntryGuid (BlobName);
+ if (Guid == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Unknown blob name \"%s\"\n", __FUNCTION__,
+ 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", __FUNCTION__, 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",
+ __FUNCTION__, 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",
+ __FUNCTION__, BlobName));
+ } else {
+ Status = EFI_ACCESS_DENIED;
+ DEBUG ((DEBUG_ERROR, "%a: Hash comparison failed for \"%s\"\n",
+ __FUNCTION__, BlobName));
+ }
+ return Status;
+ }
+
+ DEBUG ((DEBUG_ERROR, "%a: Hash GUID %g not found in table\n", __FUNCTION__,
+ 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",
+ __FUNCTION__));
+
+ mHashesTable = (HASH_TABLE *)Ptr->Data;
+ mHashesTableSize = Ptr->Len - sizeof Ptr->Guid - sizeof Ptr->Len;
+
+ DEBUG ((DEBUG_VERBOSE, "%a: mHashesTable=0x%p, Size=%u\n", __FUNCTION__,
+ mHashesTable, mHashesTableSize));
+
+ return RETURN_SUCCESS;
+}
diff --git a/OvmfPkg/OvmfPkg.ci.yaml b/OvmfPkg/OvmfPkg.ci.yaml
index 9326e6baa6..7459b84d80 100644
--- a/OvmfPkg/OvmfPkg.ci.yaml
+++ b/OvmfPkg/OvmfPkg.ci.yaml
@@ -43,6 +43,7 @@
## options defined .pytool/Plugin/DependencyCheck
"DependencyCheck": {
"AcceptableDependencies": [
+ "CryptoPkg/CryptoPkg.dec",
"MdePkg/MdePkg.dec",
"MdeModulePkg/MdeModulePkg.dec",
"OvmfPkg/OvmfPkg.dec",