]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.c
OvmfPkg/TlsAuthConfigLib: configure trusted cipher suites for HTTPS boot
[mirror_edk2.git] / OvmfPkg / Library / TlsAuthConfigLib / TlsAuthConfigLib.c
CommitLineData
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
10 This program and the accompanying materials are licensed and made available\r
11 under the terms and conditions of the BSD License which accompanies this\r
12 distribution. The full text of the license may be found at\r
13 http://opensource.org/licenses/bsd-license.php\r
14\r
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
16 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
17\r
18**/\r
19\r
20#include <Uefi/UefiBaseType.h>\r
21#include <Uefi/UefiSpec.h>\r
22\r
ba9c8a8c 23#include <Guid/HttpTlsCipherList.h>\r
9c7d0d49
LE
24#include <Guid/TlsAuthentication.h>\r
25\r
26#include <Library/BaseLib.h>\r
27#include <Library/DebugLib.h>\r
28#include <Library/MemoryAllocationLib.h>\r
29#include <Library/QemuFwCfgLib.h>\r
30#include <Library/UefiRuntimeServicesTableLib.h>\r
31\r
32/**\r
33 Read the list of trusted CA certificates from the fw_cfg file\r
34 "etc/edk2/https/cacerts", and store it to\r
35 gEfiTlsCaCertificateGuid:EFI_TLS_CA_CERTIFICATE_VARIABLE.\r
36\r
37 The contents are validated (for well-formedness) by NetworkPkg/HttpDxe.\r
38**/\r
39STATIC\r
40VOID\r
41SetCaCerts (\r
42 VOID\r
43 )\r
44{\r
45 EFI_STATUS Status;\r
46 FIRMWARE_CONFIG_ITEM HttpsCaCertsItem;\r
47 UINTN HttpsCaCertsSize;\r
48 VOID *HttpsCaCerts;\r
49\r
50 Status = QemuFwCfgFindFile ("etc/edk2/https/cacerts", &HttpsCaCertsItem,\r
51 &HttpsCaCertsSize);\r
52 if (EFI_ERROR (Status)) {\r
53 DEBUG ((DEBUG_VERBOSE, "%a:%a: not touching CA cert list\n",\r
54 gEfiCallerBaseName, __FUNCTION__));\r
55 return;\r
56 }\r
57\r
58 //\r
59 // Delete the current EFI_TLS_CA_CERTIFICATE_VARIABLE if it exists. This\r
60 // serves two purposes:\r
61 //\r
62 // (a) If the variable exists with EFI_VARIABLE_NON_VOLATILE attribute, we\r
63 // cannot make it volatile without deleting it first.\r
64 //\r
65 // (b) If we fail to recreate the variable later, deleting the current one is\r
66 // still justified if the fw_cfg file exists. Emptying the set of trusted\r
67 // CA certificates will fail HTTPS boot, which is better than trusting\r
68 // any certificate that's possibly missing from the fw_cfg file.\r
69 //\r
70 Status = gRT->SetVariable (\r
71 EFI_TLS_CA_CERTIFICATE_VARIABLE, // VariableName\r
72 &gEfiTlsCaCertificateGuid, // VendorGuid\r
73 0, // Attributes\r
74 0, // DataSize\r
75 NULL // Data\r
76 );\r
77 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
78 //\r
79 // This is fatal.\r
80 //\r
81 DEBUG ((DEBUG_ERROR, "%a:%a: failed to delete %g:\"%s\"\n",\r
82 gEfiCallerBaseName, __FUNCTION__, &gEfiTlsCaCertificateGuid,\r
83 EFI_TLS_CA_CERTIFICATE_VARIABLE));\r
84 ASSERT_EFI_ERROR (Status);\r
85 CpuDeadLoop ();\r
86 }\r
87\r
88 if (HttpsCaCertsSize == 0) {\r
89 DEBUG ((DEBUG_VERBOSE, "%a:%a: applied empty CA cert list\n",\r
90 gEfiCallerBaseName, __FUNCTION__));\r
91 return;\r
92 }\r
93\r
94 HttpsCaCerts = AllocatePool (HttpsCaCertsSize);\r
95 if (HttpsCaCerts == NULL) {\r
96 DEBUG ((DEBUG_ERROR, "%a:%a: failed to allocate HttpsCaCerts\n",\r
97 gEfiCallerBaseName, __FUNCTION__));\r
98 return;\r
99 }\r
100\r
101 QemuFwCfgSelectItem (HttpsCaCertsItem);\r
102 QemuFwCfgReadBytes (HttpsCaCertsSize, HttpsCaCerts);\r
103\r
104 Status = gRT->SetVariable (\r
105 EFI_TLS_CA_CERTIFICATE_VARIABLE, // VariableName\r
106 &gEfiTlsCaCertificateGuid, // VendorGuid\r
107 EFI_VARIABLE_BOOTSERVICE_ACCESS, // Attributes\r
108 HttpsCaCertsSize, // DataSize\r
109 HttpsCaCerts // Data\r
110 );\r
111 if (EFI_ERROR (Status)) {\r
112 DEBUG ((DEBUG_ERROR, "%a:%a: failed to set %g:\"%s\": %r\n",\r
113 gEfiCallerBaseName, __FUNCTION__, &gEfiTlsCaCertificateGuid,\r
114 EFI_TLS_CA_CERTIFICATE_VARIABLE, Status));\r
115 goto FreeHttpsCaCerts;\r
116 }\r
117\r
118 DEBUG ((DEBUG_VERBOSE, "%a:%a: stored CA cert list (%Lu byte(s))\n",\r
119 gEfiCallerBaseName, __FUNCTION__, (UINT64)HttpsCaCertsSize));\r
120\r
121FreeHttpsCaCerts:\r
122 FreePool (HttpsCaCerts);\r
123}\r
124\r
ba9c8a8c
LE
125/**\r
126 Read the list of trusted cipher suites from the fw_cfg file\r
127 "etc/edk2/https/ciphers", and store it to\r
128 gEdkiiHttpTlsCipherListGuid:EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE.\r
129\r
130 The contents are propagated by NetworkPkg/HttpDxe to NetworkPkg/TlsDxe; the\r
131 list is processed by the latter.\r
132**/\r
133STATIC\r
134VOID\r
135SetCipherSuites (\r
136 VOID\r
137 )\r
138{\r
139 EFI_STATUS Status;\r
140 FIRMWARE_CONFIG_ITEM HttpsCiphersItem;\r
141 UINTN HttpsCiphersSize;\r
142 VOID *HttpsCiphers;\r
143\r
144 Status = QemuFwCfgFindFile ("etc/edk2/https/ciphers", &HttpsCiphersItem,\r
145 &HttpsCiphersSize);\r
146 if (EFI_ERROR (Status)) {\r
147 DEBUG ((DEBUG_VERBOSE, "%a:%a: not touching cipher suites\n",\r
148 gEfiCallerBaseName, __FUNCTION__));\r
149 return;\r
150 }\r
151 //\r
152 // From this point on, any failure is fatal. An ordered cipher preference\r
153 // list is available from QEMU, thus we cannot let the firmware attempt HTTPS\r
154 // boot with either pre-existent or non-existent preferences. An empty set of\r
155 // cipher suites does not fail HTTPS boot automatically; the default cipher\r
156 // suite preferences would take effect, and we must prevent that.\r
157 //\r
158 // Delete the current EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE if it exists. If\r
159 // the variable exists with EFI_VARIABLE_NON_VOLATILE attribute, we cannot\r
160 // make it volatile without deleting it first.\r
161 //\r
162 Status = gRT->SetVariable (\r
163 EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE, // VariableName\r
164 &gEdkiiHttpTlsCipherListGuid, // VendorGuid\r
165 0, // Attributes\r
166 0, // DataSize\r
167 NULL // Data\r
168 );\r
169 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
170 DEBUG ((DEBUG_ERROR, "%a:%a: failed to delete %g:\"%s\"\n",\r
171 gEfiCallerBaseName, __FUNCTION__, &gEdkiiHttpTlsCipherListGuid,\r
172 EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE));\r
173 goto Done;\r
174 }\r
175\r
176 if (HttpsCiphersSize == 0) {\r
177 DEBUG ((DEBUG_ERROR, "%a:%a: list of cipher suites must not be empty\n",\r
178 gEfiCallerBaseName, __FUNCTION__));\r
179 Status = EFI_INVALID_PARAMETER;\r
180 goto Done;\r
181 }\r
182\r
183 HttpsCiphers = AllocatePool (HttpsCiphersSize);\r
184 if (HttpsCiphers == NULL) {\r
185 DEBUG ((DEBUG_ERROR, "%a:%a: failed to allocate HttpsCiphers\n",\r
186 gEfiCallerBaseName, __FUNCTION__));\r
187 Status = EFI_OUT_OF_RESOURCES;\r
188 goto Done;\r
189 }\r
190\r
191 QemuFwCfgSelectItem (HttpsCiphersItem);\r
192 QemuFwCfgReadBytes (HttpsCiphersSize, HttpsCiphers);\r
193\r
194 Status = gRT->SetVariable (\r
195 EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE, // VariableName\r
196 &gEdkiiHttpTlsCipherListGuid, // VendorGuid\r
197 EFI_VARIABLE_BOOTSERVICE_ACCESS, // Attributes\r
198 HttpsCiphersSize, // DataSize\r
199 HttpsCiphers // Data\r
200 );\r
201 if (EFI_ERROR (Status)) {\r
202 DEBUG ((DEBUG_ERROR, "%a:%a: failed to set %g:\"%s\"\n",\r
203 gEfiCallerBaseName, __FUNCTION__, &gEdkiiHttpTlsCipherListGuid,\r
204 EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE));\r
205 goto FreeHttpsCiphers;\r
206 }\r
207\r
208 DEBUG ((DEBUG_VERBOSE, "%a:%a: stored list of cipher suites (%Lu byte(s))\n",\r
209 gEfiCallerBaseName, __FUNCTION__, (UINT64)HttpsCiphersSize));\r
210\r
211FreeHttpsCiphers:\r
212 FreePool (HttpsCiphers);\r
213\r
214Done:\r
215 if (EFI_ERROR (Status)) {\r
216 ASSERT_EFI_ERROR (Status);\r
217 CpuDeadLoop ();\r
218 }\r
219}\r
220\r
9c7d0d49
LE
221RETURN_STATUS\r
222EFIAPI\r
223TlsAuthConfigInit (\r
224 VOID\r
225 )\r
226{\r
227 SetCaCerts ();\r
ba9c8a8c 228 SetCipherSuites ();\r
9c7d0d49
LE
229\r
230 return RETURN_SUCCESS;\r
231}\r