]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/DxeImageVerificationLib/Measurement.c
SecurityPkg: Tcg2Dxe: Use UEFI_VARIABLE_DATA
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / Measurement.c
1 /** @file
2 Measure TCG required variable.
3
4 Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <PiDxe.h>
16 #include <Guid/ImageAuthentication.h>
17 #include <IndustryStandard/UefiTcgPlatform.h>
18
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Library/UefiRuntimeServicesTableLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/BaseLib.h>
25 #include <Library/TpmMeasurementLib.h>
26
27 typedef struct {
28 CHAR16 *VariableName;
29 EFI_GUID *VendorGuid;
30 } VARIABLE_TYPE;
31
32 typedef struct {
33 CHAR16 *VariableName;
34 EFI_GUID *VendorGuid;
35 VOID *Data;
36 UINTN Size;
37 } VARIABLE_RECORD;
38
39 #define MEASURED_AUTHORITY_COUNT_MAX 0x100
40
41 UINTN mMeasuredAuthorityCount = 0;
42 UINTN mMeasuredAuthorityCountMax = 0;
43 VARIABLE_RECORD *mMeasuredAuthorityList = NULL;
44
45 VARIABLE_TYPE mVariableType[] = {
46 {EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid},
47 };
48
49 /**
50 This function will check if VarName should be recorded and return the address of VarName if it is needed.
51
52 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
53
54 @return the address of VarName.
55 **/
56 CHAR16 *
57 AssignVarName (
58 IN CHAR16 *VarName
59 )
60 {
61 UINTN Index;
62
63 for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
64 if (StrCmp (VarName, mVariableType[Index].VariableName) == 0) {
65 return mVariableType[Index].VariableName;
66 }
67 }
68
69 return NULL;
70 }
71
72 /**
73 This function will check if VendorGuid should be recorded and return the address of VendorGuid if it is needed.
74
75 @param[in] VendorGuid A unique identifier for the vendor.
76
77 @return the address of VendorGuid.
78 **/
79 EFI_GUID *
80 AssignVendorGuid (
81 IN EFI_GUID *VendorGuid
82 )
83 {
84 UINTN Index;
85
86 for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
87 if (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid)) {
88 return mVariableType[Index].VendorGuid;
89 }
90 }
91
92 return NULL;
93 }
94
95 /**
96 This function will add variable information to MeasuredAuthorityList.
97
98 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
99 @param[in] VendorGuid A unique identifier for the vendor.
100 @param[in] VarData The content of the variable data.
101 @param[in] VarSize The size of the variable data.
102
103 @retval EFI_SUCCESS Operation completed successfully.
104 @retval EFI_OUT_OF_RESOURCES Out of memory.
105 **/
106 EFI_STATUS
107 AddDataMeasured (
108 IN CHAR16 *VarName,
109 IN EFI_GUID *VendorGuid,
110 IN VOID *Data,
111 IN UINTN Size
112 )
113 {
114 VARIABLE_RECORD *NewMeasuredAuthorityList;
115
116 ASSERT (mMeasuredAuthorityCount <= mMeasuredAuthorityCountMax);
117 if (mMeasuredAuthorityCount == mMeasuredAuthorityCountMax) {
118 //
119 // Need enlarge
120 //
121 NewMeasuredAuthorityList = AllocateZeroPool (sizeof(VARIABLE_RECORD) * (mMeasuredAuthorityCountMax + MEASURED_AUTHORITY_COUNT_MAX));
122 if (NewMeasuredAuthorityList == NULL) {
123 return EFI_OUT_OF_RESOURCES;
124 }
125 if (mMeasuredAuthorityList != NULL) {
126 CopyMem (NewMeasuredAuthorityList, mMeasuredAuthorityList, sizeof(VARIABLE_RECORD) * mMeasuredAuthorityCount);
127 FreePool (mMeasuredAuthorityList);
128 }
129 mMeasuredAuthorityList = NewMeasuredAuthorityList;
130 mMeasuredAuthorityCountMax += MEASURED_AUTHORITY_COUNT_MAX;
131 }
132
133 //
134 // Add new entry
135 //
136 mMeasuredAuthorityList[mMeasuredAuthorityCount].VariableName = AssignVarName (VarName);
137 mMeasuredAuthorityList[mMeasuredAuthorityCount].VendorGuid = AssignVendorGuid (VendorGuid);
138 mMeasuredAuthorityList[mMeasuredAuthorityCount].Size = Size;
139 mMeasuredAuthorityList[mMeasuredAuthorityCount].Data = AllocatePool (Size);
140 if (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data == NULL) {
141 return EFI_OUT_OF_RESOURCES;
142 }
143 CopyMem (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data, Data, Size);
144 mMeasuredAuthorityCount++;
145
146 return EFI_SUCCESS;
147 }
148
149 /**
150 This function will return if this variable is already measured.
151
152 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
153 @param[in] VendorGuid A unique identifier for the vendor.
154 @param[in] VarData The content of the variable data.
155 @param[in] VarSize The size of the variable data.
156
157 @retval TRUE The data is already measured.
158 @retval FALSE The data is not measured yet.
159 **/
160 BOOLEAN
161 IsDataMeasured (
162 IN CHAR16 *VarName,
163 IN EFI_GUID *VendorGuid,
164 IN VOID *Data,
165 IN UINTN Size
166 )
167 {
168 UINTN Index;
169
170 for (Index = 0; Index < mMeasuredAuthorityCount; Index++) {
171 if ((StrCmp (VarName, mMeasuredAuthorityList[Index].VariableName) == 0) &&
172 (CompareGuid (VendorGuid, mMeasuredAuthorityList[Index].VendorGuid)) &&
173 (CompareMem (Data, mMeasuredAuthorityList[Index].Data, Size) == 0) &&
174 (Size == mMeasuredAuthorityList[Index].Size)) {
175 return TRUE;
176 }
177 }
178
179 return FALSE;
180 }
181
182 /**
183 This function will return if this variable is SecureAuthority Variable.
184
185 @param[in] VariableName A Null-terminated string that is the name of the vendor's variable.
186 @param[in] VendorGuid A unique identifier for the vendor.
187
188 @retval TRUE This is SecureAuthority Variable
189 @retval FALSE This is not SecureAuthority Variable
190 **/
191 BOOLEAN
192 IsSecureAuthorityVariable (
193 IN CHAR16 *VariableName,
194 IN EFI_GUID *VendorGuid
195 )
196 {
197 UINTN Index;
198
199 for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
200 if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) &&
201 (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) {
202 return TRUE;
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 ((EFI_D_INFO, "DxeImageVerification: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY));
263 DEBUG ((EFI_D_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 ((EFI_D_ERROR, "MeasureSecureAuthorityVariable - IsDataMeasured\n"));
305 return ;
306 }
307
308 Status = MeasureVariable (
309 VariableName,
310 VendorGuid,
311 Data,
312 DataSize
313 );
314 DEBUG ((EFI_D_INFO, "MeasureBootPolicyVariable - %r\n", Status));
315
316 if (!EFI_ERROR (Status)) {
317 AddDataMeasured (VariableName, VendorGuid, Data, DataSize);
318 }
319
320 return ;
321 }