3 Blob verifier library that uses SEV hashes table. The hashes table holds the
4 allowed hashes of the kernel, initrd, and cmdline blobs.
6 Copyright (C) 2021, IBM Corporation
8 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/BaseCryptLib.h>
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/BlobVerifierLib.h>
18 The SEV Hashes table must be in encrypted memory and has the table
19 and its entries described by
21 <GUID>|UINT16 <len>|<data>
23 With the whole table GUID being 9438d606-4f22-4cc9-b479-a793d411fd21
25 The current possible table entries are for the kernel, the initrd
28 4de79437-abd2-427f-b835-d5b172d2045b kernel
29 44baf731-3a2f-4bd7-9af1-41e29169781d initrd
30 97d02dd8-bd20-4c94-aa78-e7714d36ab2a cmdline
32 The size of the entry is used to identify the hash, but the
33 expectation is that it will be 32 bytes of SHA-256.
36 #define SEV_HASH_TABLE_GUID \
37 (GUID) { 0x9438d606, 0x4f22, 0x4cc9, { 0xb4, 0x79, 0xa7, 0x93, 0xd4, 0x11, 0xfd, 0x21 } }
38 #define SEV_KERNEL_HASH_GUID \
39 (GUID) { 0x4de79437, 0xabd2, 0x427f, { 0xb8, 0x35, 0xd5, 0xb1, 0x72, 0xd2, 0x04, 0x5b } }
40 #define SEV_INITRD_HASH_GUID \
41 (GUID) { 0x44baf731, 0x3a2f, 0x4bd7, { 0x9a, 0xf1, 0x41, 0xe2, 0x91, 0x69, 0x78, 0x1d } }
42 #define SEV_CMDLINE_HASH_GUID \
43 (GUID) { 0x97d02dd8, 0xbd20, 0x4c94, { 0xaa, 0x78, 0xe7, 0x71, 0x4d, 0x36, 0xab, 0x2a } }
45 STATIC CONST EFI_GUID mSevKernelHashGuid
= SEV_KERNEL_HASH_GUID
;
46 STATIC CONST EFI_GUID mSevInitrdHashGuid
= SEV_INITRD_HASH_GUID
;
47 STATIC CONST EFI_GUID mSevCmdlineHashGuid
= SEV_CMDLINE_HASH_GUID
;
57 STATIC HASH_TABLE
*mHashesTable
;
58 STATIC UINT16 mHashesTableSize
;
63 IN CONST CHAR16
*BlobName
66 if (StrCmp (BlobName
, L
"kernel") == 0) {
67 return &mSevKernelHashGuid
;
68 } else if (StrCmp (BlobName
, L
"initrd") == 0) {
69 return &mSevInitrdHashGuid
;
70 } else if (StrCmp (BlobName
, L
"cmdline") == 0) {
71 return &mSevCmdlineHashGuid
;
78 Verify blob from an external source.
80 @param[in] BlobName The name of the blob
81 @param[in] Buf The data of the blob
82 @param[in] BufSize The size of the blob in bytes
84 @retval EFI_SUCCESS The blob was verified successfully.
85 @retval EFI_ACCESS_DENIED The blob could not be verified, and therefore
86 should be considered non-secure.
91 IN CONST CHAR16
*BlobName
,
100 if (mHashesTable
== NULL
|| mHashesTableSize
== 0) {
102 "%a: Verifier called but no hashes table discoverd in MEMFD\n",
104 return EFI_ACCESS_DENIED
;
107 Guid
= FindBlobEntryGuid (BlobName
);
109 DEBUG ((DEBUG_ERROR
, "%a: Unknown blob name \"%s\"\n", __FUNCTION__
,
111 return EFI_ACCESS_DENIED
;
115 // Remaining is INT32 to catch underflow in case Entry->Len has a
116 // very high UINT16 value
118 for (Entry
= mHashesTable
, Remaining
= mHashesTableSize
;
119 Remaining
>= sizeof *Entry
&& Remaining
>= Entry
->Len
;
120 Remaining
-= Entry
->Len
,
121 Entry
= (HASH_TABLE
*)((UINT8
*)Entry
+ Entry
->Len
)) {
124 UINT8 Hash
[SHA256_DIGEST_SIZE
];
126 if (!CompareGuid (&Entry
->Guid
, Guid
)) {
130 DEBUG ((DEBUG_INFO
, "%a: Found GUID %g in table\n", __FUNCTION__
, Guid
));
132 EntrySize
= Entry
->Len
- sizeof Entry
->Guid
- sizeof Entry
->Len
;
133 if (EntrySize
!= SHA256_DIGEST_SIZE
) {
134 DEBUG ((DEBUG_ERROR
, "%a: Hash has the wrong size %d != %d\n",
135 __FUNCTION__
, EntrySize
, SHA256_DIGEST_SIZE
));
136 return EFI_ACCESS_DENIED
;
140 // Calculate the buffer's hash and verify that it is identical to the
141 // expected hash table entry
143 Sha256HashAll (Buf
, BufSize
, Hash
);
145 if (CompareMem (Entry
->Data
, Hash
, EntrySize
) == 0) {
146 Status
= EFI_SUCCESS
;
147 DEBUG ((DEBUG_INFO
, "%a: Hash comparison succeeded for \"%s\"\n",
148 __FUNCTION__
, BlobName
));
150 Status
= EFI_ACCESS_DENIED
;
151 DEBUG ((DEBUG_ERROR
, "%a: Hash comparison failed for \"%s\"\n",
152 __FUNCTION__
, BlobName
));
157 DEBUG ((DEBUG_ERROR
, "%a: Hash GUID %g not found in table\n", __FUNCTION__
,
159 return EFI_ACCESS_DENIED
;
163 Locate the SEV hashes table.
165 This function always returns success, even if the table can't be found. The
166 subsequent VerifyBlob calls will fail if no table was found.
168 @retval RETURN_SUCCESS The hashes table is set up correctly, or there is no
173 BlobVerifierLibSevHashesConstructor (
181 mHashesTableSize
= 0;
183 Ptr
= (void *)(UINTN
)FixedPcdGet64 (PcdQemuHashTableBase
);
184 Size
= FixedPcdGet32 (PcdQemuHashTableSize
);
186 if (Ptr
== NULL
|| Size
< sizeof *Ptr
||
187 !CompareGuid (&Ptr
->Guid
, &SEV_HASH_TABLE_GUID
) ||
188 Ptr
->Len
< sizeof *Ptr
|| Ptr
->Len
> Size
) {
189 return RETURN_SUCCESS
;
192 DEBUG ((DEBUG_INFO
, "%a: Found injected hashes table in secure location\n",
195 mHashesTable
= (HASH_TABLE
*)Ptr
->Data
;
196 mHashesTableSize
= Ptr
->Len
- sizeof Ptr
->Guid
- sizeof Ptr
->Len
;
198 DEBUG ((DEBUG_VERBOSE
, "%a: mHashesTable=0x%p, Size=%u\n", __FUNCTION__
,
199 mHashesTable
, mHashesTableSize
));
201 return RETURN_SUCCESS
;