]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / AmdSev / BlobVerifierLibSevHashes / BlobVerifierSevHashes.c
1 /** @file
2
3 Blob verifier library that uses SEV hashes table. The hashes table holds the
4 allowed hashes of the kernel, initrd, and cmdline blobs.
5
6 Copyright (C) 2021, IBM Corporation
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9 **/
10
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>
16
17 /**
18 The SEV Hashes table must be in encrypted memory and has the table
19 and its entries described by
20
21 <GUID>|UINT16 <len>|<data>
22
23 With the whole table GUID being 9438d606-4f22-4cc9-b479-a793d411fd21
24
25 The current possible table entries are for the kernel, the initrd
26 and the cmdline:
27
28 4de79437-abd2-427f-b835-d5b172d2045b kernel
29 44baf731-3a2f-4bd7-9af1-41e29169781d initrd
30 97d02dd8-bd20-4c94-aa78-e7714d36ab2a cmdline
31
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.
34 **/
35
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 } }
44
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;
48
49 #pragma pack (1)
50 typedef struct {
51 GUID Guid;
52 UINT16 Len;
53 UINT8 Data[];
54 } HASH_TABLE;
55 #pragma pack ()
56
57 STATIC HASH_TABLE *mHashesTable;
58 STATIC UINT16 mHashesTableSize;
59
60 STATIC
61 CONST GUID *
62 FindBlobEntryGuid (
63 IN CONST CHAR16 *BlobName
64 )
65 {
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;
72 } else {
73 return NULL;
74 }
75 }
76
77 /**
78 Verify blob from an external source.
79
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
83
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.
87 **/
88 EFI_STATUS
89 EFIAPI
90 VerifyBlob (
91 IN CONST CHAR16 *BlobName,
92 IN CONST VOID *Buf,
93 IN UINT32 BufSize
94 )
95 {
96 CONST GUID *Guid;
97 INT32 Remaining;
98 HASH_TABLE *Entry;
99
100 if ((mHashesTable == NULL) || (mHashesTableSize == 0)) {
101 DEBUG ((
102 DEBUG_ERROR,
103 "%a: Verifier called but no hashes table discoverd in MEMFD\n",
104 __FUNCTION__
105 ));
106 return EFI_ACCESS_DENIED;
107 }
108
109 Guid = FindBlobEntryGuid (BlobName);
110 if (Guid == NULL) {
111 DEBUG ((
112 DEBUG_ERROR,
113 "%a: Unknown blob name \"%s\"\n",
114 __FUNCTION__,
115 BlobName
116 ));
117 return EFI_ACCESS_DENIED;
118 }
119
120 //
121 // Remaining is INT32 to catch underflow in case Entry->Len has a
122 // very high UINT16 value
123 //
124 for (Entry = mHashesTable, Remaining = mHashesTableSize;
125 Remaining >= sizeof *Entry && Remaining >= Entry->Len;
126 Remaining -= Entry->Len,
127 Entry = (HASH_TABLE *)((UINT8 *)Entry + Entry->Len))
128 {
129 UINTN EntrySize;
130 EFI_STATUS Status;
131 UINT8 Hash[SHA256_DIGEST_SIZE];
132
133 if (!CompareGuid (&Entry->Guid, Guid)) {
134 continue;
135 }
136
137 DEBUG ((DEBUG_INFO, "%a: Found GUID %g in table\n", __FUNCTION__, Guid));
138
139 EntrySize = Entry->Len - sizeof Entry->Guid - sizeof Entry->Len;
140 if (EntrySize != SHA256_DIGEST_SIZE) {
141 DEBUG ((
142 DEBUG_ERROR,
143 "%a: Hash has the wrong size %d != %d\n",
144 __FUNCTION__,
145 EntrySize,
146 SHA256_DIGEST_SIZE
147 ));
148 return EFI_ACCESS_DENIED;
149 }
150
151 //
152 // Calculate the buffer's hash and verify that it is identical to the
153 // expected hash table entry
154 //
155 Sha256HashAll (Buf, BufSize, Hash);
156
157 if (CompareMem (Entry->Data, Hash, EntrySize) == 0) {
158 Status = EFI_SUCCESS;
159 DEBUG ((
160 DEBUG_INFO,
161 "%a: Hash comparison succeeded for \"%s\"\n",
162 __FUNCTION__,
163 BlobName
164 ));
165 } else {
166 Status = EFI_ACCESS_DENIED;
167 DEBUG ((
168 DEBUG_ERROR,
169 "%a: Hash comparison failed for \"%s\"\n",
170 __FUNCTION__,
171 BlobName
172 ));
173 }
174
175 return Status;
176 }
177
178 DEBUG ((
179 DEBUG_ERROR,
180 "%a: Hash GUID %g not found in table\n",
181 __FUNCTION__,
182 Guid
183 ));
184 return EFI_ACCESS_DENIED;
185 }
186
187 /**
188 Locate the SEV hashes table.
189
190 This function always returns success, even if the table can't be found. The
191 subsequent VerifyBlob calls will fail if no table was found.
192
193 @retval RETURN_SUCCESS The hashes table is set up correctly, or there is no
194 hashes table
195 **/
196 RETURN_STATUS
197 EFIAPI
198 BlobVerifierLibSevHashesConstructor (
199 VOID
200 )
201 {
202 HASH_TABLE *Ptr;
203 UINT32 Size;
204
205 mHashesTable = NULL;
206 mHashesTableSize = 0;
207
208 Ptr = (void *)(UINTN)FixedPcdGet64 (PcdQemuHashTableBase);
209 Size = FixedPcdGet32 (PcdQemuHashTableSize);
210
211 if ((Ptr == NULL) || (Size < sizeof *Ptr) ||
212 !CompareGuid (&Ptr->Guid, &SEV_HASH_TABLE_GUID) ||
213 (Ptr->Len < sizeof *Ptr) || (Ptr->Len > Size))
214 {
215 return RETURN_SUCCESS;
216 }
217
218 DEBUG ((
219 DEBUG_INFO,
220 "%a: Found injected hashes table in secure location\n",
221 __FUNCTION__
222 ));
223
224 mHashesTable = (HASH_TABLE *)Ptr->Data;
225 mHashesTableSize = Ptr->Len - sizeof Ptr->Guid - sizeof Ptr->Len;
226
227 DEBUG ((
228 DEBUG_VERBOSE,
229 "%a: mHashesTable=0x%p, Size=%u\n",
230 __FUNCTION__,
231 mHashesTable,
232 mHashesTableSize
233 ));
234
235 return RETURN_SUCCESS;
236 }