]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHierarchyLib.c
SecurityPkg: Apply uncrustify changes
[mirror_edk2.git] / SecurityPkg / Library / PeiDxeTpmPlatformHierarchyLib / PeiDxeTpmPlatformHierarchyLib.c
CommitLineData
610d8073
SB
1/** @file\r
2 TPM Platform Hierarchy configuration library.\r
3\r
4 This library provides functions for customizing the TPM's Platform Hierarchy\r
5 Authorization Value (platformAuth) and Platform Hierarchy Authorization\r
6 Policy (platformPolicy) can be defined through this function.\r
7\r
8 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
9 Copyright (c) Microsoft Corporation.<BR>\r
10 SPDX-License-Identifier: BSD-2-Clause-Patent\r
11\r
12 @par Specification Reference:\r
13 https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance/\r
14**/\r
15\r
16#include <Uefi.h>\r
17\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/MemoryAllocationLib.h>\r
610d8073
SB
21#include <Library/RngLib.h>\r
22#include <Library/Tpm2CommandLib.h>\r
23#include <Library/Tpm2DeviceLib.h>\r
24\r
25//\r
26// The authorization value may be no larger than the digest produced by the hash\r
27// algorithm used for context integrity.\r
28//\r
610d8073 29\r
c411b485 30UINT16 mAuthSize;\r
610d8073
SB
31\r
32/**\r
33 Generate high-quality entropy source through RDRAND.\r
34\r
35 @param[in] Length Size of the buffer, in bytes, to fill with.\r
36 @param[out] Entropy Pointer to the buffer to store the entropy data.\r
37\r
38 @retval EFI_SUCCESS Entropy generation succeeded.\r
39 @retval EFI_NOT_READY Failed to request random data.\r
40\r
41**/\r
42EFI_STATUS\r
43EFIAPI\r
44RdRandGenerateEntropy (\r
c411b485
MK
45 IN UINTN Length,\r
46 OUT UINT8 *Entropy\r
610d8073
SB
47 )\r
48{\r
49 EFI_STATUS Status;\r
50 UINTN BlockCount;\r
51 UINT64 Seed[2];\r
52 UINT8 *Ptr;\r
53\r
c411b485
MK
54 Status = EFI_NOT_READY;\r
55 BlockCount = Length / sizeof (Seed);\r
56 Ptr = (UINT8 *)Entropy;\r
610d8073
SB
57\r
58 //\r
59 // Generate high-quality seed for DRBG Entropy\r
60 //\r
61 while (BlockCount > 0) {\r
62 Status = GetRandomNumber128 (Seed);\r
63 if (EFI_ERROR (Status)) {\r
64 return Status;\r
65 }\r
c411b485
MK
66\r
67 CopyMem (Ptr, Seed, sizeof (Seed));\r
610d8073
SB
68\r
69 BlockCount--;\r
c411b485 70 Ptr = Ptr + sizeof (Seed);\r
610d8073
SB
71 }\r
72\r
73 //\r
74 // Populate the remained data as request.\r
75 //\r
76 Status = GetRandomNumber128 (Seed);\r
77 if (EFI_ERROR (Status)) {\r
78 return Status;\r
79 }\r
c411b485
MK
80\r
81 CopyMem (Ptr, Seed, (Length % sizeof (Seed)));\r
610d8073
SB
82\r
83 return Status;\r
84}\r
85\r
86/**\r
87 This function returns the maximum size of TPM2B_AUTH; this structure is used for an authorization value\r
88 and limits an authValue to being no larger than the largest digest produced by a TPM.\r
89\r
90 @param[out] AuthSize Tpm2 Auth size\r
91\r
92 @retval EFI_SUCCESS Auth size returned.\r
93 @retval EFI_DEVICE_ERROR Can not return platform auth due to device error.\r
94\r
95**/\r
96EFI_STATUS\r
97EFIAPI\r
98GetAuthSize (\r
c411b485 99 OUT UINT16 *AuthSize\r
610d8073
SB
100 )\r
101{\r
c411b485
MK
102 EFI_STATUS Status;\r
103 TPML_PCR_SELECTION Pcrs;\r
104 UINTN Index;\r
105 UINT16 DigestSize;\r
610d8073
SB
106\r
107 Status = EFI_SUCCESS;\r
108\r
109 while (mAuthSize == 0) {\r
610d8073
SB
110 mAuthSize = SHA1_DIGEST_SIZE;\r
111 ZeroMem (&Pcrs, sizeof (TPML_PCR_SELECTION));\r
112 Status = Tpm2GetCapabilityPcrs (&Pcrs);\r
113\r
114 if (EFI_ERROR (Status)) {\r
115 DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));\r
116 break;\r
117 }\r
118\r
119 DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs - %08x\n", Pcrs.count));\r
120\r
121 for (Index = 0; Index < Pcrs.count; Index++) {\r
122 DEBUG ((DEBUG_ERROR, "alg - %x\n", Pcrs.pcrSelections[Index].hash));\r
123\r
124 switch (Pcrs.pcrSelections[Index].hash) {\r
c411b485
MK
125 case TPM_ALG_SHA1:\r
126 DigestSize = SHA1_DIGEST_SIZE;\r
127 break;\r
128 case TPM_ALG_SHA256:\r
129 DigestSize = SHA256_DIGEST_SIZE;\r
130 break;\r
131 case TPM_ALG_SHA384:\r
132 DigestSize = SHA384_DIGEST_SIZE;\r
133 break;\r
134 case TPM_ALG_SHA512:\r
135 DigestSize = SHA512_DIGEST_SIZE;\r
136 break;\r
137 case TPM_ALG_SM3_256:\r
138 DigestSize = SM3_256_DIGEST_SIZE;\r
139 break;\r
140 default:\r
141 DigestSize = SHA1_DIGEST_SIZE;\r
142 break;\r
610d8073
SB
143 }\r
144\r
145 if (DigestSize > mAuthSize) {\r
146 mAuthSize = DigestSize;\r
147 }\r
148 }\r
c411b485 149\r
610d8073
SB
150 break;\r
151 }\r
152\r
153 *AuthSize = mAuthSize;\r
154 return Status;\r
155}\r
156\r
157/**\r
158 Set PlatformAuth to random value.\r
159**/\r
160VOID\r
161RandomizePlatformAuth (\r
162 VOID\r
163 )\r
164{\r
c411b485
MK
165 EFI_STATUS Status;\r
166 UINT16 AuthSize;\r
167 TPM2B_AUTH NewPlatformAuth;\r
610d8073
SB
168\r
169 //\r
170 // Send Tpm2HierarchyChange Auth with random value to avoid PlatformAuth being null\r
171 //\r
172\r
173 GetAuthSize (&AuthSize);\r
174\r
610d8073
SB
175 NewPlatformAuth.size = AuthSize;\r
176\r
177 //\r
4d5f39cd 178 // Create the random bytes in the destination buffer\r
610d8073 179 //\r
610d8073 180\r
4d5f39cd 181 RdRandGenerateEntropy (NewPlatformAuth.size, NewPlatformAuth.buffer);\r
610d8073
SB
182\r
183 //\r
184 // Send Tpm2HierarchyChangeAuth command with the new Auth value\r
185 //\r
186 Status = Tpm2HierarchyChangeAuth (TPM_RH_PLATFORM, NULL, &NewPlatformAuth);\r
187 DEBUG ((DEBUG_INFO, "Tpm2HierarchyChangeAuth Result: - %r\n", Status));\r
188 ZeroMem (NewPlatformAuth.buffer, AuthSize);\r
610d8073
SB
189}\r
190\r
191/**\r
192 Disable the TPM platform hierarchy.\r
193\r
194 @retval EFI_SUCCESS The TPM was disabled successfully.\r
195 @retval Others An error occurred attempting to disable the TPM platform hierarchy.\r
196\r
197**/\r
198EFI_STATUS\r
199DisableTpmPlatformHierarchy (\r
200 VOID\r
201 )\r
202{\r
203 EFI_STATUS Status;\r
204\r
205 // Make sure that we have use of the TPM.\r
206 Status = Tpm2RequestUseTpm ();\r
207 if (EFI_ERROR (Status)) {\r
208 DEBUG ((DEBUG_ERROR, "%a:%a() - Tpm2RequestUseTpm Failed! %r\n", gEfiCallerBaseName, __FUNCTION__, Status));\r
209 ASSERT_EFI_ERROR (Status);\r
210 return Status;\r
211 }\r
212\r
213 // Let's do what we can to shut down the hierarchies.\r
214\r
215 // Disable the PH NV.\r
216 // IMPORTANT NOTE: We *should* be able to disable the PH NV here, but TPM parts have\r
217 // been known to store the EK cert in the PH NV. If we disable it, the\r
218 // EK cert will be unreadable.\r
219\r
220 // Disable the PH.\r
221 Status = Tpm2HierarchyControl (\r
222 TPM_RH_PLATFORM, // AuthHandle\r
223 NULL, // AuthSession\r
224 TPM_RH_PLATFORM, // Hierarchy\r
225 NO // State\r
226 );\r
227 DEBUG ((DEBUG_VERBOSE, "%a:%a() - Disable PH = %r\n", gEfiCallerBaseName, __FUNCTION__, Status));\r
228 if (EFI_ERROR (Status)) {\r
229 DEBUG ((DEBUG_ERROR, "%a:%a() - Disable PH Failed! %r\n", gEfiCallerBaseName, __FUNCTION__, Status));\r
230 ASSERT_EFI_ERROR (Status);\r
231 }\r
232\r
233 return Status;\r
234}\r
235\r
236/**\r
237 This service defines the configuration of the Platform Hierarchy Authorization Value (platformAuth)\r
2906e572 238 and Platform Hierarchy Authorization Policy (platformPolicy).\r
610d8073
SB
239\r
240**/\r
241VOID\r
242EFIAPI\r
243ConfigureTpmPlatformHierarchy (\r
244 )\r
245{\r
246 if (PcdGetBool (PcdRandomizePlatformHierarchy)) {\r
247 //\r
248 // Send Tpm2HierarchyChange Auth with random value to avoid PlatformAuth being null\r
249 //\r
250 RandomizePlatformAuth ();\r
251 } else {\r
252 //\r
253 // Disable the hierarchy entirely (do not randomize it)\r
254 //\r
255 DisableTpmPlatformHierarchy ();\r
256 }\r
257}\r