]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/PeilessStartupLib/IntelTdx.c
OvmfPkg/IntelTdx: Measure Td HobList and Configuration FV
[mirror_edk2.git] / OvmfPkg / Library / PeilessStartupLib / IntelTdx.c
CommitLineData
4b0a6226
MX
1/** @file\r
2 Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
3 SPDX-License-Identifier: BSD-2-Clause-Patent\r
4**/\r
5\r
6#include <PiPei.h>\r
7#include <Library/BaseLib.h>\r
8#include <Library/BaseMemoryLib.h>\r
9#include <Library/DebugLib.h>\r
10#include <Guid/VariableFormat.h>\r
11#include <Guid/SystemNvDataGuid.h>\r
12#include "PeilessStartupInternal.h"\r
13\r
14/**\r
15 Check padding data all bit should be 1.\r
16\r
17 @param[in] Buffer - A pointer to buffer header\r
18 @param[in] BufferSize - Buffer size\r
19\r
20 @retval TRUE - The padding data is valid.\r
21 @retval TRUE - The padding data is invalid.\r
22\r
23**/\r
24BOOLEAN\r
25CheckPaddingData (\r
26 IN UINT8 *Buffer,\r
27 IN UINT32 BufferSize\r
28 )\r
29{\r
30 UINT32 index;\r
31\r
32 for (index = 0; index < BufferSize; index++) {\r
33 if (Buffer[index] != 0xFF) {\r
34 return FALSE;\r
35 }\r
36 }\r
37\r
38 return TRUE;\r
39}\r
40\r
41/**\r
42 Check the integrity of CFV data.\r
43\r
44 @param[in] TdxCfvBase - A pointer to CFV header\r
45 @param[in] TdxCfvSize - CFV data size\r
46\r
47 @retval TRUE - The CFV data is valid.\r
48 @retval FALSE - The CFV data is invalid.\r
49\r
50**/\r
51BOOLEAN\r
52EFIAPI\r
53TdxValidateCfv (\r
54 IN UINT8 *TdxCfvBase,\r
55 IN UINT32 TdxCfvSize\r
56 )\r
57{\r
58 UINT16 Checksum;\r
59 UINTN VariableBase;\r
60 UINT32 VariableOffset;\r
61 UINT32 VariableOffsetBeforeAlign;\r
62 EFI_FIRMWARE_VOLUME_HEADER *CfvFvHeader;\r
63 VARIABLE_STORE_HEADER *CfvVariableStoreHeader;\r
64 AUTHENTICATED_VARIABLE_HEADER *VariableHeader;\r
65\r
66 static EFI_GUID FvHdrGUID = EFI_SYSTEM_NV_DATA_FV_GUID;\r
67 static EFI_GUID VarStoreHdrGUID = EFI_AUTHENTICATED_VARIABLE_GUID;\r
68\r
69 VariableOffset = 0;\r
70\r
71 if (TdxCfvBase == NULL) {\r
72 DEBUG ((DEBUG_ERROR, "TDX CFV: CFV pointer is NULL\n"));\r
73 return FALSE;\r
74 }\r
75\r
76 //\r
77 // Verify the header zerovetor, filesystemguid,\r
78 // revision, signature, attributes, fvlength, checksum\r
79 // HeaderLength cannot be an odd number\r
80 //\r
81 CfvFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)TdxCfvBase;\r
82\r
83 if ((!IsZeroBuffer (CfvFvHeader->ZeroVector, 16)) ||\r
84 (!CompareGuid (&FvHdrGUID, &CfvFvHeader->FileSystemGuid)) ||\r
85 (CfvFvHeader->Signature != EFI_FVH_SIGNATURE) ||\r
86 (CfvFvHeader->Attributes != 0x4feff) ||\r
87 (CfvFvHeader->Revision != EFI_FVH_REVISION) ||\r
88 (CfvFvHeader->FvLength != TdxCfvSize)\r
89 )\r
90 {\r
91 DEBUG ((DEBUG_ERROR, "TDX CFV: Basic FV headers were invalid\n"));\r
92 return FALSE;\r
93 }\r
94\r
95 //\r
96 // Verify the header checksum\r
97 //\r
98 Checksum = CalculateSum16 ((VOID *)CfvFvHeader, CfvFvHeader->HeaderLength);\r
99\r
100 if (Checksum != 0) {\r
101 DEBUG ((DEBUG_ERROR, "TDX CFV: FV checksum was invalid\n"));\r
102 return FALSE;\r
103 }\r
104\r
105 //\r
106 // Verify the header signature, size, format, state\r
107 //\r
108 CfvVariableStoreHeader = (VARIABLE_STORE_HEADER *)(TdxCfvBase + CfvFvHeader->HeaderLength);\r
109 if ((!CompareGuid (&VarStoreHdrGUID, &CfvVariableStoreHeader->Signature)) ||\r
110 (CfvVariableStoreHeader->Format != VARIABLE_STORE_FORMATTED) ||\r
111 (CfvVariableStoreHeader->State != VARIABLE_STORE_HEALTHY) ||\r
112 (CfvVariableStoreHeader->Size > (CfvFvHeader->FvLength - CfvFvHeader->HeaderLength)) ||\r
113 (CfvVariableStoreHeader->Size < sizeof (VARIABLE_STORE_HEADER))\r
114 )\r
115 {\r
116 DEBUG ((DEBUG_ERROR, "TDX CFV: Variable Store header was invalid\n"));\r
117 return FALSE;\r
118 }\r
119\r
120 //\r
121 // Verify the header startId, state\r
122 // Verify data to the end\r
123 //\r
124 VariableBase = (UINTN)TdxCfvBase + CfvFvHeader->HeaderLength + sizeof (VARIABLE_STORE_HEADER);\r
125 while (VariableOffset < (CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) {\r
126 VariableHeader = (AUTHENTICATED_VARIABLE_HEADER *)(VariableBase + VariableOffset);\r
127 if (VariableHeader->StartId != VARIABLE_DATA) {\r
128 if (!CheckPaddingData ((UINT8 *)VariableHeader, CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - VariableOffset)) {\r
129 DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
130 return FALSE;\r
131 }\r
132\r
133 VariableOffset = CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
134 } else {\r
135 if (!((VariableHeader->State == VAR_IN_DELETED_TRANSITION) ||\r
136 (VariableHeader->State == VAR_DELETED) ||\r
137 (VariableHeader->State == VAR_HEADER_VALID_ONLY) ||\r
138 (VariableHeader->State == VAR_ADDED)))\r
139 {\r
140 DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
141 return FALSE;\r
142 }\r
143\r
144 VariableOffset += sizeof (AUTHENTICATED_VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize;\r
145 // Verify VariableOffset should be less than or equal CfvVariableStoreHeader->Size - sizeof(VARIABLE_STORE_HEADER)\r
146 if (VariableOffset > (CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) {\r
147 DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
148 return FALSE;\r
149 }\r
150\r
151 VariableOffsetBeforeAlign = VariableOffset;\r
152 // 4 byte align\r
153 VariableOffset = (VariableOffset + 3) & (UINTN)(~3);\r
154\r
155 if (!CheckPaddingData ((UINT8 *)(VariableBase + VariableOffsetBeforeAlign), VariableOffset - VariableOffsetBeforeAlign)) {\r
156 DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
157 return FALSE;\r
158 }\r
159 }\r
160 }\r
161\r
162 return TRUE;\r
163}\r