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