Commit | Line | Data |
---|---|---|
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 | 30 | UINT16 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 | |
42 | EFI_STATUS\r | |
43 | EFIAPI\r | |
44 | RdRandGenerateEntropy (\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 | |
96 | EFI_STATUS\r | |
97 | EFIAPI\r | |
98 | GetAuthSize (\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 | |
160 | VOID\r | |
161 | RandomizePlatformAuth (\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 | |
198 | EFI_STATUS\r | |
199 | DisableTpmPlatformHierarchy (\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 | |
241 | VOID\r | |
242 | EFIAPI\r | |
243 | ConfigureTpmPlatformHierarchy (\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 |