]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/DxeImageVerificationLib/Measurement.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / Measurement.c
1 /** @file
2 Measure TCG required variable.
3
4 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <PiDxe.h>
10 #include <Guid/ImageAuthentication.h>
11 #include <IndustryStandard/UefiTcgPlatform.h>
12
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Library/UefiRuntimeServicesTableLib.h>
15 #include <Library/MemoryAllocationLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/TpmMeasurementLib.h>
20
21 typedef struct {
22 CHAR16 *VariableName;
23 EFI_GUID *VendorGuid;
24 } VARIABLE_TYPE;
25
26 typedef struct {
27 CHAR16 *VariableName;
28 EFI_GUID *VendorGuid;
29 VOID *Data;
30 UINTN Size;
31 } VARIABLE_RECORD;
32
33 #define MEASURED_AUTHORITY_COUNT_MAX 0x100
34
35 UINTN mMeasuredAuthorityCount = 0;
36 UINTN mMeasuredAuthorityCountMax = 0;
37 VARIABLE_RECORD *mMeasuredAuthorityList = NULL;
38
39 VARIABLE_TYPE mVariableType[] = {
40 { EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid },
41 };
42
43 /**
44 This function will check if VarName should be recorded and return the address of VarName if it is needed.
45
46 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
47
48 @return the address of VarName.
49 **/
50 CHAR16 *
51 AssignVarName (
52 IN CHAR16 *VarName
53 )
54 {
55 UINTN Index;
56
57 for (Index = 0; Index < sizeof (mVariableType)/sizeof (mVariableType[0]); Index++) {
58 if (StrCmp (VarName, mVariableType[Index].VariableName) == 0) {
59 return mVariableType[Index].VariableName;
60 }
61 }
62
63 return NULL;
64 }
65
66 /**
67 This function will check if VendorGuid should be recorded and return the address of VendorGuid if it is needed.
68
69 @param[in] VendorGuid A unique identifier for the vendor.
70
71 @return the address of VendorGuid.
72 **/
73 EFI_GUID *
74 AssignVendorGuid (
75 IN EFI_GUID *VendorGuid
76 )
77 {
78 UINTN Index;
79
80 for (Index = 0; Index < sizeof (mVariableType)/sizeof (mVariableType[0]); Index++) {
81 if (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid)) {
82 return mVariableType[Index].VendorGuid;
83 }
84 }
85
86 return NULL;
87 }
88
89 /**
90 This function will add variable information to MeasuredAuthorityList.
91
92 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
93 @param[in] VendorGuid A unique identifier for the vendor.
94 @param[in] VarData The content of the variable data.
95 @param[in] VarSize The size of the variable data.
96
97 @retval EFI_SUCCESS Operation completed successfully.
98 @retval EFI_OUT_OF_RESOURCES Out of memory.
99 **/
100 EFI_STATUS
101 AddDataMeasured (
102 IN CHAR16 *VarName,
103 IN EFI_GUID *VendorGuid,
104 IN VOID *Data,
105 IN UINTN Size
106 )
107 {
108 VARIABLE_RECORD *NewMeasuredAuthorityList;
109
110 ASSERT (mMeasuredAuthorityCount <= mMeasuredAuthorityCountMax);
111 if (mMeasuredAuthorityCount == mMeasuredAuthorityCountMax) {
112 //
113 // Need enlarge
114 //
115 NewMeasuredAuthorityList = AllocateZeroPool (sizeof (VARIABLE_RECORD) * (mMeasuredAuthorityCountMax + MEASURED_AUTHORITY_COUNT_MAX));
116 if (NewMeasuredAuthorityList == NULL) {
117 return EFI_OUT_OF_RESOURCES;
118 }
119
120 if (mMeasuredAuthorityList != NULL) {
121 CopyMem (NewMeasuredAuthorityList, mMeasuredAuthorityList, sizeof (VARIABLE_RECORD) * mMeasuredAuthorityCount);
122 FreePool (mMeasuredAuthorityList);
123 }
124
125 mMeasuredAuthorityList = NewMeasuredAuthorityList;
126 mMeasuredAuthorityCountMax += MEASURED_AUTHORITY_COUNT_MAX;
127 }
128
129 //
130 // Add new entry
131 //
132 mMeasuredAuthorityList[mMeasuredAuthorityCount].VariableName = AssignVarName (VarName);
133 mMeasuredAuthorityList[mMeasuredAuthorityCount].VendorGuid = AssignVendorGuid (VendorGuid);
134 mMeasuredAuthorityList[mMeasuredAuthorityCount].Size = Size;
135 mMeasuredAuthorityList[mMeasuredAuthorityCount].Data = AllocatePool (Size);
136 if (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data == NULL) {
137 return EFI_OUT_OF_RESOURCES;
138 }
139
140 CopyMem (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data, Data, Size);
141 mMeasuredAuthorityCount++;
142
143 return EFI_SUCCESS;
144 }
145
146 /**
147 This function will return if this variable is already measured.
148
149 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
150 @param[in] VendorGuid A unique identifier for the vendor.
151 @param[in] VarData The content of the variable data.
152 @param[in] VarSize The size of the variable data.
153
154 @retval TRUE The data is already measured.
155 @retval FALSE The data is not measured yet.
156 **/
157 BOOLEAN
158 IsDataMeasured (
159 IN CHAR16 *VarName,
160 IN EFI_GUID *VendorGuid,
161 IN VOID *Data,
162 IN UINTN Size
163 )
164 {
165 UINTN Index;
166
167 for (Index = 0; Index < mMeasuredAuthorityCount; Index++) {
168 if ((StrCmp (VarName, mMeasuredAuthorityList[Index].VariableName) == 0) &&
169 (CompareGuid (VendorGuid, mMeasuredAuthorityList[Index].VendorGuid)) &&
170 (CompareMem (Data, mMeasuredAuthorityList[Index].Data, Size) == 0) &&
171 (Size == mMeasuredAuthorityList[Index].Size))
172 {
173 return TRUE;
174 }
175 }
176
177 return FALSE;
178 }
179
180 /**
181 This function will return if this variable is SecureAuthority Variable.
182
183 @param[in] VariableName A Null-terminated string that is the name of the vendor's variable.
184 @param[in] VendorGuid A unique identifier for the vendor.
185
186 @retval TRUE This is SecureAuthority Variable
187 @retval FALSE This is not SecureAuthority Variable
188 **/
189 BOOLEAN
190 IsSecureAuthorityVariable (
191 IN CHAR16 *VariableName,
192 IN EFI_GUID *VendorGuid
193 )
194 {
195 UINTN Index;
196
197 for (Index = 0; Index < sizeof (mVariableType)/sizeof (mVariableType[0]); Index++) {
198 if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) &&
199 (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid)))
200 {
201 return TRUE;
202 }
203 }
204
205 return FALSE;
206 }
207
208 /**
209 Measure and log an EFI variable, and extend the measurement result into a specific PCR.
210
211 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
212 @param[in] VendorGuid A unique identifier for the vendor.
213 @param[in] VarData The content of the variable data.
214 @param[in] VarSize The size of the variable data.
215
216 @retval EFI_SUCCESS Operation completed successfully.
217 @retval EFI_OUT_OF_RESOURCES Out of memory.
218 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
219
220 **/
221 EFI_STATUS
222 EFIAPI
223 MeasureVariable (
224 IN CHAR16 *VarName,
225 IN EFI_GUID *VendorGuid,
226 IN VOID *VarData,
227 IN UINTN VarSize
228 )
229 {
230 EFI_STATUS Status;
231 UINTN VarNameLength;
232 UEFI_VARIABLE_DATA *VarLog;
233 UINT32 VarLogSize;
234
235 //
236 // The UEFI_VARIABLE_DATA.VariableData value shall be the EFI_SIGNATURE_DATA value
237 // from the EFI_SIGNATURE_LIST that contained the authority that was used to validate the image
238 //
239 VarNameLength = StrLen (VarName);
240 VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
241 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
242
243 VarLog = (UEFI_VARIABLE_DATA *)AllocateZeroPool (VarLogSize);
244 if (VarLog == NULL) {
245 return EFI_OUT_OF_RESOURCES;
246 }
247
248 CopyMem (&VarLog->VariableName, VendorGuid, sizeof (VarLog->VariableName));
249 VarLog->UnicodeNameLength = VarNameLength;
250 VarLog->VariableDataLength = VarSize;
251 CopyMem (
252 VarLog->UnicodeName,
253 VarName,
254 VarNameLength * sizeof (*VarName)
255 );
256 CopyMem (
257 (CHAR16 *)VarLog->UnicodeName + VarNameLength,
258 VarData,
259 VarSize
260 );
261
262 DEBUG ((DEBUG_INFO, "DxeImageVerification: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY));
263 DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
264
265 Status = TpmMeasureAndLogData (
266 7,
267 EV_EFI_VARIABLE_AUTHORITY,
268 VarLog,
269 VarLogSize,
270 VarLog,
271 VarLogSize
272 );
273 FreePool (VarLog);
274
275 return Status;
276 }
277
278 /**
279 SecureBoot Hook for processing image verification.
280
281 @param[in] VariableName Name of Variable to be found.
282 @param[in] VendorGuid Variable vendor GUID.
283 @param[in] DataSize Size of Data found. If size is less than the
284 data, this value contains the required size.
285 @param[in] Data Data pointer.
286
287 **/
288 VOID
289 EFIAPI
290 SecureBootHook (
291 IN CHAR16 *VariableName,
292 IN EFI_GUID *VendorGuid,
293 IN UINTN DataSize,
294 IN VOID *Data
295 )
296 {
297 EFI_STATUS Status;
298
299 if (!IsSecureAuthorityVariable (VariableName, VendorGuid)) {
300 return;
301 }
302
303 if (IsDataMeasured (VariableName, VendorGuid, Data, DataSize)) {
304 DEBUG ((DEBUG_ERROR, "MeasureSecureAuthorityVariable - IsDataMeasured\n"));
305 return;
306 }
307
308 Status = MeasureVariable (
309 VariableName,
310 VendorGuid,
311 Data,
312 DataSize
313 );
314 DEBUG ((DEBUG_INFO, "MeasureBootPolicyVariable - %r\n", Status));
315
316 if (!EFI_ERROR (Status)) {
317 AddDataMeasured (VariableName, VendorGuid, Data, DataSize);
318 }
319
320 return;
321 }