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