]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/DxeImageVerificationLib/Measurement.c
SecurityPkg: Replace BSD License with BSD+Patent License
[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 if (mMeasuredAuthorityList != NULL) {
120 CopyMem (NewMeasuredAuthorityList, mMeasuredAuthorityList, sizeof(VARIABLE_RECORD) * mMeasuredAuthorityCount);
121 FreePool (mMeasuredAuthorityList);
122 }
123 mMeasuredAuthorityList = NewMeasuredAuthorityList;
124 mMeasuredAuthorityCountMax += MEASURED_AUTHORITY_COUNT_MAX;
125 }
126
127 //
128 // Add new entry
129 //
130 mMeasuredAuthorityList[mMeasuredAuthorityCount].VariableName = AssignVarName (VarName);
131 mMeasuredAuthorityList[mMeasuredAuthorityCount].VendorGuid = AssignVendorGuid (VendorGuid);
132 mMeasuredAuthorityList[mMeasuredAuthorityCount].Size = Size;
133 mMeasuredAuthorityList[mMeasuredAuthorityCount].Data = AllocatePool (Size);
134 if (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data == NULL) {
135 return EFI_OUT_OF_RESOURCES;
136 }
137 CopyMem (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data, Data, Size);
138 mMeasuredAuthorityCount++;
139
140 return EFI_SUCCESS;
141 }
142
143 /**
144 This function will return if this variable is already measured.
145
146 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
147 @param[in] VendorGuid A unique identifier for the vendor.
148 @param[in] VarData The content of the variable data.
149 @param[in] VarSize The size of the variable data.
150
151 @retval TRUE The data is already measured.
152 @retval FALSE The data is not measured yet.
153 **/
154 BOOLEAN
155 IsDataMeasured (
156 IN CHAR16 *VarName,
157 IN EFI_GUID *VendorGuid,
158 IN VOID *Data,
159 IN UINTN Size
160 )
161 {
162 UINTN Index;
163
164 for (Index = 0; Index < mMeasuredAuthorityCount; Index++) {
165 if ((StrCmp (VarName, mMeasuredAuthorityList[Index].VariableName) == 0) &&
166 (CompareGuid (VendorGuid, mMeasuredAuthorityList[Index].VendorGuid)) &&
167 (CompareMem (Data, mMeasuredAuthorityList[Index].Data, Size) == 0) &&
168 (Size == mMeasuredAuthorityList[Index].Size)) {
169 return TRUE;
170 }
171 }
172
173 return FALSE;
174 }
175
176 /**
177 This function will return if this variable is SecureAuthority Variable.
178
179 @param[in] VariableName A Null-terminated string that is the name of the vendor's variable.
180 @param[in] VendorGuid A unique identifier for the vendor.
181
182 @retval TRUE This is SecureAuthority Variable
183 @retval FALSE This is not SecureAuthority Variable
184 **/
185 BOOLEAN
186 IsSecureAuthorityVariable (
187 IN CHAR16 *VariableName,
188 IN EFI_GUID *VendorGuid
189 )
190 {
191 UINTN Index;
192
193 for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
194 if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) &&
195 (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) {
196 return TRUE;
197 }
198 }
199 return FALSE;
200 }
201
202 /**
203 Measure and log an EFI variable, and extend the measurement result into a specific PCR.
204
205 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
206 @param[in] VendorGuid A unique identifier for the vendor.
207 @param[in] VarData The content of the variable data.
208 @param[in] VarSize The size of the variable data.
209
210 @retval EFI_SUCCESS Operation completed successfully.
211 @retval EFI_OUT_OF_RESOURCES Out of memory.
212 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
213
214 **/
215 EFI_STATUS
216 EFIAPI
217 MeasureVariable (
218 IN CHAR16 *VarName,
219 IN EFI_GUID *VendorGuid,
220 IN VOID *VarData,
221 IN UINTN VarSize
222 )
223 {
224 EFI_STATUS Status;
225 UINTN VarNameLength;
226 UEFI_VARIABLE_DATA *VarLog;
227 UINT32 VarLogSize;
228
229 //
230 // The UEFI_VARIABLE_DATA.VariableData value shall be the EFI_SIGNATURE_DATA value
231 // from the EFI_SIGNATURE_LIST that contained the authority that was used to validate the image
232 //
233 VarNameLength = StrLen (VarName);
234 VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
235 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
236
237 VarLog = (UEFI_VARIABLE_DATA *) AllocateZeroPool (VarLogSize);
238 if (VarLog == NULL) {
239 return EFI_OUT_OF_RESOURCES;
240 }
241
242 CopyMem (&VarLog->VariableName, VendorGuid, sizeof(VarLog->VariableName));
243 VarLog->UnicodeNameLength = VarNameLength;
244 VarLog->VariableDataLength = VarSize;
245 CopyMem (
246 VarLog->UnicodeName,
247 VarName,
248 VarNameLength * sizeof (*VarName)
249 );
250 CopyMem (
251 (CHAR16 *)VarLog->UnicodeName + VarNameLength,
252 VarData,
253 VarSize
254 );
255
256 DEBUG ((EFI_D_INFO, "DxeImageVerification: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY));
257 DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
258
259 Status = TpmMeasureAndLogData (
260 7,
261 EV_EFI_VARIABLE_AUTHORITY,
262 VarLog,
263 VarLogSize,
264 VarLog,
265 VarLogSize
266 );
267 FreePool (VarLog);
268
269 return Status;
270 }
271
272 /**
273 SecureBoot Hook for processing image verification.
274
275 @param[in] VariableName Name of Variable to be found.
276 @param[in] VendorGuid Variable vendor GUID.
277 @param[in] DataSize Size of Data found. If size is less than the
278 data, this value contains the required size.
279 @param[in] Data Data pointer.
280
281 **/
282 VOID
283 EFIAPI
284 SecureBootHook (
285 IN CHAR16 *VariableName,
286 IN EFI_GUID *VendorGuid,
287 IN UINTN DataSize,
288 IN VOID *Data
289 )
290 {
291 EFI_STATUS Status;
292
293 if (!IsSecureAuthorityVariable (VariableName, VendorGuid)) {
294 return ;
295 }
296
297 if (IsDataMeasured (VariableName, VendorGuid, Data, DataSize)) {
298 DEBUG ((EFI_D_ERROR, "MeasureSecureAuthorityVariable - IsDataMeasured\n"));
299 return ;
300 }
301
302 Status = MeasureVariable (
303 VariableName,
304 VendorGuid,
305 Data,
306 DataSize
307 );
308 DEBUG ((EFI_D_INFO, "MeasureBootPolicyVariable - %r\n", Status));
309
310 if (!EFI_ERROR (Status)) {
311 AddDataMeasured (VariableName, VendorGuid, Data, DataSize);
312 }
313
314 return ;
315 }