]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / AmdSev / BlobVerifierLibSevHashes / BlobVerifierSevHashes.c
CommitLineData
385b9d80
DM
1/** @file\r
2\r
3 Blob verifier library that uses SEV hashes table. The hashes table holds the\r
4 allowed hashes of the kernel, initrd, and cmdline blobs.\r
5\r
6 Copyright (C) 2021, IBM Corporation\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9**/\r
10\r
11#include <Library/BaseCryptLib.h>\r
12#include <Library/BaseLib.h>\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/DebugLib.h>\r
15#include <Library/BlobVerifierLib.h>\r
16\r
17/**\r
18 The SEV Hashes table must be in encrypted memory and has the table\r
19 and its entries described by\r
20\r
21 <GUID>|UINT16 <len>|<data>\r
22\r
23 With the whole table GUID being 9438d606-4f22-4cc9-b479-a793d411fd21\r
24\r
25 The current possible table entries are for the kernel, the initrd\r
26 and the cmdline:\r
27\r
28 4de79437-abd2-427f-b835-d5b172d2045b kernel\r
29 44baf731-3a2f-4bd7-9af1-41e29169781d initrd\r
30 97d02dd8-bd20-4c94-aa78-e7714d36ab2a cmdline\r
31\r
32 The size of the entry is used to identify the hash, but the\r
33 expectation is that it will be 32 bytes of SHA-256.\r
34**/\r
35\r
36#define SEV_HASH_TABLE_GUID \\r
37 (GUID) { 0x9438d606, 0x4f22, 0x4cc9, { 0xb4, 0x79, 0xa7, 0x93, 0xd4, 0x11, 0xfd, 0x21 } }\r
38#define SEV_KERNEL_HASH_GUID \\r
39 (GUID) { 0x4de79437, 0xabd2, 0x427f, { 0xb8, 0x35, 0xd5, 0xb1, 0x72, 0xd2, 0x04, 0x5b } }\r
40#define SEV_INITRD_HASH_GUID \\r
41 (GUID) { 0x44baf731, 0x3a2f, 0x4bd7, { 0x9a, 0xf1, 0x41, 0xe2, 0x91, 0x69, 0x78, 0x1d } }\r
42#define SEV_CMDLINE_HASH_GUID \\r
43 (GUID) { 0x97d02dd8, 0xbd20, 0x4c94, { 0xaa, 0x78, 0xe7, 0x71, 0x4d, 0x36, 0xab, 0x2a } }\r
44\r
ac0a286f
MK
45STATIC CONST EFI_GUID mSevKernelHashGuid = SEV_KERNEL_HASH_GUID;\r
46STATIC CONST EFI_GUID mSevInitrdHashGuid = SEV_INITRD_HASH_GUID;\r
47STATIC CONST EFI_GUID mSevCmdlineHashGuid = SEV_CMDLINE_HASH_GUID;\r
385b9d80
DM
48\r
49#pragma pack (1)\r
50typedef struct {\r
ac0a286f
MK
51 GUID Guid;\r
52 UINT16 Len;\r
53 UINT8 Data[];\r
385b9d80
DM
54} HASH_TABLE;\r
55#pragma pack ()\r
56\r
ac0a286f
MK
57STATIC HASH_TABLE *mHashesTable;\r
58STATIC UINT16 mHashesTableSize;\r
385b9d80
DM
59\r
60STATIC\r
ac0a286f 61CONST GUID *\r
385b9d80 62FindBlobEntryGuid (\r
ac0a286f 63 IN CONST CHAR16 *BlobName\r
385b9d80
DM
64 )\r
65{\r
66 if (StrCmp (BlobName, L"kernel") == 0) {\r
67 return &mSevKernelHashGuid;\r
68 } else if (StrCmp (BlobName, L"initrd") == 0) {\r
69 return &mSevInitrdHashGuid;\r
70 } else if (StrCmp (BlobName, L"cmdline") == 0) {\r
71 return &mSevCmdlineHashGuid;\r
72 } else {\r
73 return NULL;\r
74 }\r
75}\r
76\r
77/**\r
78 Verify blob from an external source.\r
79\r
80 @param[in] BlobName The name of the blob\r
81 @param[in] Buf The data of the blob\r
82 @param[in] BufSize The size of the blob in bytes\r
83\r
84 @retval EFI_SUCCESS The blob was verified successfully.\r
85 @retval EFI_ACCESS_DENIED The blob could not be verified, and therefore\r
86 should be considered non-secure.\r
87**/\r
88EFI_STATUS\r
89EFIAPI\r
90VerifyBlob (\r
ac0a286f
MK
91 IN CONST CHAR16 *BlobName,\r
92 IN CONST VOID *Buf,\r
93 IN UINT32 BufSize\r
385b9d80
DM
94 )\r
95{\r
ac0a286f
MK
96 CONST GUID *Guid;\r
97 INT32 Remaining;\r
98 HASH_TABLE *Entry;\r
385b9d80 99\r
ac0a286f
MK
100 if ((mHashesTable == NULL) || (mHashesTableSize == 0)) {\r
101 DEBUG ((\r
102 DEBUG_ERROR,\r
385b9d80 103 "%a: Verifier called but no hashes table discoverd in MEMFD\n",\r
ac0a286f
MK
104 __FUNCTION__\r
105 ));\r
385b9d80
DM
106 return EFI_ACCESS_DENIED;\r
107 }\r
108\r
109 Guid = FindBlobEntryGuid (BlobName);\r
110 if (Guid == NULL) {\r
ac0a286f
MK
111 DEBUG ((\r
112 DEBUG_ERROR,\r
113 "%a: Unknown blob name \"%s\"\n",\r
114 __FUNCTION__,\r
115 BlobName\r
116 ));\r
385b9d80
DM
117 return EFI_ACCESS_DENIED;\r
118 }\r
119\r
120 //\r
121 // Remaining is INT32 to catch underflow in case Entry->Len has a\r
122 // very high UINT16 value\r
123 //\r
124 for (Entry = mHashesTable, Remaining = mHashesTableSize;\r
125 Remaining >= sizeof *Entry && Remaining >= Entry->Len;\r
126 Remaining -= Entry->Len,\r
ac0a286f
MK
127 Entry = (HASH_TABLE *)((UINT8 *)Entry + Entry->Len))\r
128 {\r
129 UINTN EntrySize;\r
130 EFI_STATUS Status;\r
131 UINT8 Hash[SHA256_DIGEST_SIZE];\r
385b9d80
DM
132\r
133 if (!CompareGuid (&Entry->Guid, Guid)) {\r
134 continue;\r
135 }\r
136\r
137 DEBUG ((DEBUG_INFO, "%a: Found GUID %g in table\n", __FUNCTION__, Guid));\r
138\r
139 EntrySize = Entry->Len - sizeof Entry->Guid - sizeof Entry->Len;\r
140 if (EntrySize != SHA256_DIGEST_SIZE) {\r
ac0a286f
MK
141 DEBUG ((\r
142 DEBUG_ERROR,\r
143 "%a: Hash has the wrong size %d != %d\n",\r
144 __FUNCTION__,\r
145 EntrySize,\r
146 SHA256_DIGEST_SIZE\r
147 ));\r
385b9d80
DM
148 return EFI_ACCESS_DENIED;\r
149 }\r
150\r
151 //\r
152 // Calculate the buffer's hash and verify that it is identical to the\r
153 // expected hash table entry\r
154 //\r
155 Sha256HashAll (Buf, BufSize, Hash);\r
156\r
157 if (CompareMem (Entry->Data, Hash, EntrySize) == 0) {\r
158 Status = EFI_SUCCESS;\r
ac0a286f
MK
159 DEBUG ((\r
160 DEBUG_INFO,\r
161 "%a: Hash comparison succeeded for \"%s\"\n",\r
162 __FUNCTION__,\r
163 BlobName\r
164 ));\r
385b9d80
DM
165 } else {\r
166 Status = EFI_ACCESS_DENIED;\r
ac0a286f
MK
167 DEBUG ((\r
168 DEBUG_ERROR,\r
169 "%a: Hash comparison failed for \"%s\"\n",\r
170 __FUNCTION__,\r
171 BlobName\r
172 ));\r
385b9d80 173 }\r
ac0a286f 174\r
385b9d80
DM
175 return Status;\r
176 }\r
177\r
ac0a286f
MK
178 DEBUG ((\r
179 DEBUG_ERROR,\r
180 "%a: Hash GUID %g not found in table\n",\r
181 __FUNCTION__,\r
182 Guid\r
183 ));\r
385b9d80
DM
184 return EFI_ACCESS_DENIED;\r
185}\r
186\r
187/**\r
188 Locate the SEV hashes table.\r
189\r
190 This function always returns success, even if the table can't be found. The\r
191 subsequent VerifyBlob calls will fail if no table was found.\r
192\r
193 @retval RETURN_SUCCESS The hashes table is set up correctly, or there is no\r
194 hashes table\r
195**/\r
196RETURN_STATUS\r
197EFIAPI\r
198BlobVerifierLibSevHashesConstructor (\r
199 VOID\r
200 )\r
201{\r
ac0a286f
MK
202 HASH_TABLE *Ptr;\r
203 UINT32 Size;\r
385b9d80 204\r
ac0a286f 205 mHashesTable = NULL;\r
385b9d80
DM
206 mHashesTableSize = 0;\r
207\r
ac0a286f 208 Ptr = (void *)(UINTN)FixedPcdGet64 (PcdQemuHashTableBase);\r
385b9d80
DM
209 Size = FixedPcdGet32 (PcdQemuHashTableSize);\r
210\r
ac0a286f 211 if ((Ptr == NULL) || (Size < sizeof *Ptr) ||\r
385b9d80 212 !CompareGuid (&Ptr->Guid, &SEV_HASH_TABLE_GUID) ||\r
ac0a286f
MK
213 (Ptr->Len < sizeof *Ptr) || (Ptr->Len > Size))\r
214 {\r
385b9d80
DM
215 return RETURN_SUCCESS;\r
216 }\r
217\r
ac0a286f
MK
218 DEBUG ((\r
219 DEBUG_INFO,\r
220 "%a: Found injected hashes table in secure location\n",\r
221 __FUNCTION__\r
222 ));\r
385b9d80 223\r
ac0a286f 224 mHashesTable = (HASH_TABLE *)Ptr->Data;\r
385b9d80
DM
225 mHashesTableSize = Ptr->Len - sizeof Ptr->Guid - sizeof Ptr->Len;\r
226\r
ac0a286f
MK
227 DEBUG ((\r
228 DEBUG_VERBOSE,\r
229 "%a: mHashesTable=0x%p, Size=%u\n",\r
230 __FUNCTION__,\r
231 mHashesTable,\r
232 mHashesTableSize\r
233 ));\r
385b9d80
DM
234\r
235 return RETURN_SUCCESS;\r
236}\r