• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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