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