]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHierarchyLib.c
SecurityPkg/Tcg: Make Tcg2PlatformDxe buildable and fix style issues
[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 CopyMem (Ptr, Seed, sizeof(Seed));
67
68 BlockCount--;
69 Ptr = Ptr + sizeof(Seed);
70 }
71
72 //
73 // Populate the remained data as request.
74 //
75 Status = GetRandomNumber128 (Seed);
76 if (EFI_ERROR (Status)) {
77 return Status;
78 }
79 CopyMem (Ptr, Seed, (Length % sizeof(Seed)));
80
81 return Status;
82 }
83
84 /**
85 This function returns the maximum size of TPM2B_AUTH; this structure is used for an authorization value
86 and limits an authValue to being no larger than the largest digest produced by a TPM.
87
88 @param[out] AuthSize Tpm2 Auth size
89
90 @retval EFI_SUCCESS Auth size returned.
91 @retval EFI_DEVICE_ERROR Can not return platform auth due to device error.
92
93 **/
94 EFI_STATUS
95 EFIAPI
96 GetAuthSize (
97 OUT UINT16 *AuthSize
98 )
99 {
100 EFI_STATUS Status;
101 TPML_PCR_SELECTION Pcrs;
102 UINTN Index;
103 UINT16 DigestSize;
104
105 Status = EFI_SUCCESS;
106
107 while (mAuthSize == 0) {
108
109 mAuthSize = SHA1_DIGEST_SIZE;
110 ZeroMem (&Pcrs, sizeof (TPML_PCR_SELECTION));
111 Status = Tpm2GetCapabilityPcrs (&Pcrs);
112
113 if (EFI_ERROR (Status)) {
114 DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));
115 break;
116 }
117
118 DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityPcrs - %08x\n", Pcrs.count));
119
120 for (Index = 0; Index < Pcrs.count; Index++) {
121 DEBUG ((DEBUG_ERROR, "alg - %x\n", Pcrs.pcrSelections[Index].hash));
122
123 switch (Pcrs.pcrSelections[Index].hash) {
124 case TPM_ALG_SHA1:
125 DigestSize = SHA1_DIGEST_SIZE;
126 break;
127 case TPM_ALG_SHA256:
128 DigestSize = SHA256_DIGEST_SIZE;
129 break;
130 case TPM_ALG_SHA384:
131 DigestSize = SHA384_DIGEST_SIZE;
132 break;
133 case TPM_ALG_SHA512:
134 DigestSize = SHA512_DIGEST_SIZE;
135 break;
136 case TPM_ALG_SM3_256:
137 DigestSize = SM3_256_DIGEST_SIZE;
138 break;
139 default:
140 DigestSize = SHA1_DIGEST_SIZE;
141 break;
142 }
143
144 if (DigestSize > mAuthSize) {
145 mAuthSize = DigestSize;
146 }
147 }
148 break;
149 }
150
151 *AuthSize = mAuthSize;
152 return Status;
153 }
154
155 /**
156 Set PlatformAuth to random value.
157 **/
158 VOID
159 RandomizePlatformAuth (
160 VOID
161 )
162 {
163 EFI_STATUS Status;
164 UINT16 AuthSize;
165 TPM2B_AUTH NewPlatformAuth;
166
167 //
168 // Send Tpm2HierarchyChange Auth with random value to avoid PlatformAuth being null
169 //
170
171 GetAuthSize (&AuthSize);
172
173 NewPlatformAuth.size = AuthSize;
174
175 //
176 // Create the random bytes in the destination buffer
177 //
178
179 RdRandGenerateEntropy (NewPlatformAuth.size, NewPlatformAuth.buffer);
180
181 //
182 // Send Tpm2HierarchyChangeAuth command with the new Auth value
183 //
184 Status = Tpm2HierarchyChangeAuth (TPM_RH_PLATFORM, NULL, &NewPlatformAuth);
185 DEBUG ((DEBUG_INFO, "Tpm2HierarchyChangeAuth Result: - %r\n", Status));
186 ZeroMem (NewPlatformAuth.buffer, AuthSize);
187 }
188
189 /**
190 Disable the TPM platform hierarchy.
191
192 @retval EFI_SUCCESS The TPM was disabled successfully.
193 @retval Others An error occurred attempting to disable the TPM platform hierarchy.
194
195 **/
196 EFI_STATUS
197 DisableTpmPlatformHierarchy (
198 VOID
199 )
200 {
201 EFI_STATUS Status;
202
203 // Make sure that we have use of the TPM.
204 Status = Tpm2RequestUseTpm ();
205 if (EFI_ERROR (Status)) {
206 DEBUG ((DEBUG_ERROR, "%a:%a() - Tpm2RequestUseTpm Failed! %r\n", gEfiCallerBaseName, __FUNCTION__, Status));
207 ASSERT_EFI_ERROR (Status);
208 return Status;
209 }
210
211 // Let's do what we can to shut down the hierarchies.
212
213 // Disable the PH NV.
214 // IMPORTANT NOTE: We *should* be able to disable the PH NV here, but TPM parts have
215 // been known to store the EK cert in the PH NV. If we disable it, the
216 // EK cert will be unreadable.
217
218 // Disable the PH.
219 Status = Tpm2HierarchyControl (
220 TPM_RH_PLATFORM, // AuthHandle
221 NULL, // AuthSession
222 TPM_RH_PLATFORM, // Hierarchy
223 NO // State
224 );
225 DEBUG ((DEBUG_VERBOSE, "%a:%a() - Disable PH = %r\n", gEfiCallerBaseName, __FUNCTION__, Status));
226 if (EFI_ERROR (Status)) {
227 DEBUG ((DEBUG_ERROR, "%a:%a() - Disable PH Failed! %r\n", gEfiCallerBaseName, __FUNCTION__, Status));
228 ASSERT_EFI_ERROR (Status);
229 }
230
231 return Status;
232 }
233
234 /**
235 This service defines the configuration of the Platform Hierarchy Authorization Value (platformAuth)
236 and Platform Hierarchy Authorization Policy (platformPolicy).
237
238 **/
239 VOID
240 EFIAPI
241 ConfigureTpmPlatformHierarchy (
242 )
243 {
244 if (PcdGetBool (PcdRandomizePlatformHierarchy)) {
245 //
246 // Send Tpm2HierarchyChange Auth with random value to avoid PlatformAuth being null
247 //
248 RandomizePlatformAuth ();
249 } else {
250 //
251 // Disable the hierarchy entirely (do not randomize it)
252 //
253 DisableTpmPlatformHierarchy ();
254 }
255 }