]>
Commit | Line | Data |
---|---|---|
9c7d0d49 LE |
1 | /** @file\r |
2 | \r | |
3 | A hook-in library for NetworkPkg/TlsAuthConfigDxe, in order to set volatile\r | |
4 | variables related to TLS configuration, before TlsAuthConfigDxe or HttpDxe\r | |
5 | (which is a UEFI_DRIVER) consume them.\r | |
6 | \r | |
7 | Copyright (C) 2013, 2015, 2018, Red Hat, Inc.\r | |
8 | Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r | |
9 | \r | |
b26f0cf9 | 10 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
9c7d0d49 LE |
11 | \r |
12 | **/\r | |
13 | \r | |
14 | #include <Uefi/UefiBaseType.h>\r | |
15 | #include <Uefi/UefiSpec.h>\r | |
16 | \r | |
ba9c8a8c | 17 | #include <Guid/HttpTlsCipherList.h>\r |
9c7d0d49 LE |
18 | #include <Guid/TlsAuthentication.h>\r |
19 | \r | |
20 | #include <Library/BaseLib.h>\r | |
21 | #include <Library/DebugLib.h>\r | |
22 | #include <Library/MemoryAllocationLib.h>\r | |
23 | #include <Library/QemuFwCfgLib.h>\r | |
24 | #include <Library/UefiRuntimeServicesTableLib.h>\r | |
25 | \r | |
26 | /**\r | |
27 | Read the list of trusted CA certificates from the fw_cfg file\r | |
28 | "etc/edk2/https/cacerts", and store it to\r | |
29 | gEfiTlsCaCertificateGuid:EFI_TLS_CA_CERTIFICATE_VARIABLE.\r | |
30 | \r | |
31 | The contents are validated (for well-formedness) by NetworkPkg/HttpDxe.\r | |
32 | **/\r | |
33 | STATIC\r | |
34 | VOID\r | |
35 | SetCaCerts (\r | |
36 | VOID\r | |
37 | )\r | |
38 | {\r | |
ac0a286f MK |
39 | EFI_STATUS Status;\r |
40 | FIRMWARE_CONFIG_ITEM HttpsCaCertsItem;\r | |
41 | UINTN HttpsCaCertsSize;\r | |
42 | VOID *HttpsCaCerts;\r | |
9c7d0d49 | 43 | \r |
ac0a286f MK |
44 | Status = QemuFwCfgFindFile (\r |
45 | "etc/edk2/https/cacerts",\r | |
46 | &HttpsCaCertsItem,\r | |
47 | &HttpsCaCertsSize\r | |
48 | );\r | |
9c7d0d49 | 49 | if (EFI_ERROR (Status)) {\r |
ac0a286f MK |
50 | DEBUG ((\r |
51 | DEBUG_VERBOSE,\r | |
52 | "%a:%a: not touching CA cert list\n",\r | |
53 | gEfiCallerBaseName,\r | |
54 | __FUNCTION__\r | |
55 | ));\r | |
9c7d0d49 LE |
56 | return;\r |
57 | }\r | |
58 | \r | |
59 | //\r | |
60 | // Delete the current EFI_TLS_CA_CERTIFICATE_VARIABLE if it exists. This\r | |
61 | // serves two purposes:\r | |
62 | //\r | |
63 | // (a) If the variable exists with EFI_VARIABLE_NON_VOLATILE attribute, we\r | |
64 | // cannot make it volatile without deleting it first.\r | |
65 | //\r | |
66 | // (b) If we fail to recreate the variable later, deleting the current one is\r | |
67 | // still justified if the fw_cfg file exists. Emptying the set of trusted\r | |
68 | // CA certificates will fail HTTPS boot, which is better than trusting\r | |
69 | // any certificate that's possibly missing from the fw_cfg file.\r | |
70 | //\r | |
71 | Status = gRT->SetVariable (\r | |
72 | EFI_TLS_CA_CERTIFICATE_VARIABLE, // VariableName\r | |
73 | &gEfiTlsCaCertificateGuid, // VendorGuid\r | |
74 | 0, // Attributes\r | |
75 | 0, // DataSize\r | |
76 | NULL // Data\r | |
77 | );\r | |
78 | if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r | |
79 | //\r | |
80 | // This is fatal.\r | |
81 | //\r | |
ac0a286f MK |
82 | DEBUG ((\r |
83 | DEBUG_ERROR,\r | |
84 | "%a:%a: failed to delete %g:\"%s\"\n",\r | |
85 | gEfiCallerBaseName,\r | |
86 | __FUNCTION__,\r | |
87 | &gEfiTlsCaCertificateGuid,\r | |
88 | EFI_TLS_CA_CERTIFICATE_VARIABLE\r | |
89 | ));\r | |
9c7d0d49 LE |
90 | ASSERT_EFI_ERROR (Status);\r |
91 | CpuDeadLoop ();\r | |
92 | }\r | |
93 | \r | |
94 | if (HttpsCaCertsSize == 0) {\r | |
ac0a286f MK |
95 | DEBUG ((\r |
96 | DEBUG_VERBOSE,\r | |
97 | "%a:%a: applied empty CA cert list\n",\r | |
98 | gEfiCallerBaseName,\r | |
99 | __FUNCTION__\r | |
100 | ));\r | |
9c7d0d49 LE |
101 | return;\r |
102 | }\r | |
103 | \r | |
104 | HttpsCaCerts = AllocatePool (HttpsCaCertsSize);\r | |
105 | if (HttpsCaCerts == NULL) {\r | |
ac0a286f MK |
106 | DEBUG ((\r |
107 | DEBUG_ERROR,\r | |
108 | "%a:%a: failed to allocate HttpsCaCerts\n",\r | |
109 | gEfiCallerBaseName,\r | |
110 | __FUNCTION__\r | |
111 | ));\r | |
9c7d0d49 LE |
112 | return;\r |
113 | }\r | |
114 | \r | |
115 | QemuFwCfgSelectItem (HttpsCaCertsItem);\r | |
116 | QemuFwCfgReadBytes (HttpsCaCertsSize, HttpsCaCerts);\r | |
117 | \r | |
118 | Status = gRT->SetVariable (\r | |
119 | EFI_TLS_CA_CERTIFICATE_VARIABLE, // VariableName\r | |
120 | &gEfiTlsCaCertificateGuid, // VendorGuid\r | |
121 | EFI_VARIABLE_BOOTSERVICE_ACCESS, // Attributes\r | |
122 | HttpsCaCertsSize, // DataSize\r | |
123 | HttpsCaCerts // Data\r | |
124 | );\r | |
125 | if (EFI_ERROR (Status)) {\r | |
ac0a286f MK |
126 | DEBUG ((\r |
127 | DEBUG_ERROR,\r | |
128 | "%a:%a: failed to set %g:\"%s\": %r\n",\r | |
129 | gEfiCallerBaseName,\r | |
130 | __FUNCTION__,\r | |
131 | &gEfiTlsCaCertificateGuid,\r | |
132 | EFI_TLS_CA_CERTIFICATE_VARIABLE,\r | |
133 | Status\r | |
134 | ));\r | |
9c7d0d49 LE |
135 | goto FreeHttpsCaCerts;\r |
136 | }\r | |
137 | \r | |
ac0a286f MK |
138 | DEBUG ((\r |
139 | DEBUG_VERBOSE,\r | |
140 | "%a:%a: stored CA cert list (%Lu byte(s))\n",\r | |
141 | gEfiCallerBaseName,\r | |
142 | __FUNCTION__,\r | |
143 | (UINT64)HttpsCaCertsSize\r | |
144 | ));\r | |
9c7d0d49 LE |
145 | \r |
146 | FreeHttpsCaCerts:\r | |
147 | FreePool (HttpsCaCerts);\r | |
148 | }\r | |
149 | \r | |
ba9c8a8c LE |
150 | /**\r |
151 | Read the list of trusted cipher suites from the fw_cfg file\r | |
152 | "etc/edk2/https/ciphers", and store it to\r | |
153 | gEdkiiHttpTlsCipherListGuid:EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE.\r | |
154 | \r | |
155 | The contents are propagated by NetworkPkg/HttpDxe to NetworkPkg/TlsDxe; the\r | |
156 | list is processed by the latter.\r | |
157 | **/\r | |
158 | STATIC\r | |
159 | VOID\r | |
160 | SetCipherSuites (\r | |
161 | VOID\r | |
162 | )\r | |
163 | {\r | |
ac0a286f MK |
164 | EFI_STATUS Status;\r |
165 | FIRMWARE_CONFIG_ITEM HttpsCiphersItem;\r | |
166 | UINTN HttpsCiphersSize;\r | |
167 | VOID *HttpsCiphers;\r | |
ba9c8a8c | 168 | \r |
ac0a286f MK |
169 | Status = QemuFwCfgFindFile (\r |
170 | "etc/edk2/https/ciphers",\r | |
171 | &HttpsCiphersItem,\r | |
172 | &HttpsCiphersSize\r | |
173 | );\r | |
ba9c8a8c | 174 | if (EFI_ERROR (Status)) {\r |
ac0a286f MK |
175 | DEBUG ((\r |
176 | DEBUG_VERBOSE,\r | |
177 | "%a:%a: not touching cipher suites\n",\r | |
178 | gEfiCallerBaseName,\r | |
179 | __FUNCTION__\r | |
180 | ));\r | |
ba9c8a8c LE |
181 | return;\r |
182 | }\r | |
ac0a286f | 183 | \r |
ba9c8a8c LE |
184 | //\r |
185 | // From this point on, any failure is fatal. An ordered cipher preference\r | |
186 | // list is available from QEMU, thus we cannot let the firmware attempt HTTPS\r | |
187 | // boot with either pre-existent or non-existent preferences. An empty set of\r | |
188 | // cipher suites does not fail HTTPS boot automatically; the default cipher\r | |
189 | // suite preferences would take effect, and we must prevent that.\r | |
190 | //\r | |
191 | // Delete the current EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE if it exists. If\r | |
192 | // the variable exists with EFI_VARIABLE_NON_VOLATILE attribute, we cannot\r | |
193 | // make it volatile without deleting it first.\r | |
194 | //\r | |
195 | Status = gRT->SetVariable (\r | |
196 | EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE, // VariableName\r | |
197 | &gEdkiiHttpTlsCipherListGuid, // VendorGuid\r | |
198 | 0, // Attributes\r | |
199 | 0, // DataSize\r | |
200 | NULL // Data\r | |
201 | );\r | |
202 | if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r | |
ac0a286f MK |
203 | DEBUG ((\r |
204 | DEBUG_ERROR,\r | |
205 | "%a:%a: failed to delete %g:\"%s\"\n",\r | |
206 | gEfiCallerBaseName,\r | |
207 | __FUNCTION__,\r | |
208 | &gEdkiiHttpTlsCipherListGuid,\r | |
209 | EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE\r | |
210 | ));\r | |
ba9c8a8c LE |
211 | goto Done;\r |
212 | }\r | |
213 | \r | |
214 | if (HttpsCiphersSize == 0) {\r | |
ac0a286f MK |
215 | DEBUG ((\r |
216 | DEBUG_ERROR,\r | |
217 | "%a:%a: list of cipher suites must not be empty\n",\r | |
218 | gEfiCallerBaseName,\r | |
219 | __FUNCTION__\r | |
220 | ));\r | |
ba9c8a8c LE |
221 | Status = EFI_INVALID_PARAMETER;\r |
222 | goto Done;\r | |
223 | }\r | |
224 | \r | |
225 | HttpsCiphers = AllocatePool (HttpsCiphersSize);\r | |
226 | if (HttpsCiphers == NULL) {\r | |
ac0a286f MK |
227 | DEBUG ((\r |
228 | DEBUG_ERROR,\r | |
229 | "%a:%a: failed to allocate HttpsCiphers\n",\r | |
230 | gEfiCallerBaseName,\r | |
231 | __FUNCTION__\r | |
232 | ));\r | |
ba9c8a8c LE |
233 | Status = EFI_OUT_OF_RESOURCES;\r |
234 | goto Done;\r | |
235 | }\r | |
236 | \r | |
237 | QemuFwCfgSelectItem (HttpsCiphersItem);\r | |
238 | QemuFwCfgReadBytes (HttpsCiphersSize, HttpsCiphers);\r | |
239 | \r | |
240 | Status = gRT->SetVariable (\r | |
241 | EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE, // VariableName\r | |
242 | &gEdkiiHttpTlsCipherListGuid, // VendorGuid\r | |
243 | EFI_VARIABLE_BOOTSERVICE_ACCESS, // Attributes\r | |
244 | HttpsCiphersSize, // DataSize\r | |
245 | HttpsCiphers // Data\r | |
246 | );\r | |
247 | if (EFI_ERROR (Status)) {\r | |
ac0a286f MK |
248 | DEBUG ((\r |
249 | DEBUG_ERROR,\r | |
250 | "%a:%a: failed to set %g:\"%s\"\n",\r | |
251 | gEfiCallerBaseName,\r | |
252 | __FUNCTION__,\r | |
253 | &gEdkiiHttpTlsCipherListGuid,\r | |
254 | EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE\r | |
255 | ));\r | |
ba9c8a8c LE |
256 | goto FreeHttpsCiphers;\r |
257 | }\r | |
258 | \r | |
ac0a286f MK |
259 | DEBUG ((\r |
260 | DEBUG_VERBOSE,\r | |
261 | "%a:%a: stored list of cipher suites (%Lu byte(s))\n",\r | |
262 | gEfiCallerBaseName,\r | |
263 | __FUNCTION__,\r | |
264 | (UINT64)HttpsCiphersSize\r | |
265 | ));\r | |
ba9c8a8c LE |
266 | \r |
267 | FreeHttpsCiphers:\r | |
268 | FreePool (HttpsCiphers);\r | |
269 | \r | |
270 | Done:\r | |
271 | if (EFI_ERROR (Status)) {\r | |
272 | ASSERT_EFI_ERROR (Status);\r | |
273 | CpuDeadLoop ();\r | |
274 | }\r | |
275 | }\r | |
276 | \r | |
9c7d0d49 LE |
277 | RETURN_STATUS\r |
278 | EFIAPI\r | |
279 | TlsAuthConfigInit (\r | |
280 | VOID\r | |
281 | )\r | |
282 | {\r | |
283 | SetCaCerts ();\r | |
ba9c8a8c | 284 | SetCipherSuites ();\r |
9c7d0d49 LE |
285 | \r |
286 | return RETURN_SUCCESS;\r | |
287 | }\r |