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.
7 Copyright (C) 2013, 2015, 2018, Red Hat, Inc.
8 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
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
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.
20 #include <Uefi/UefiBaseType.h>
21 #include <Uefi/UefiSpec.h>
23 #include <Guid/HttpTlsCipherList.h>
24 #include <Guid/TlsAuthentication.h>
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>
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.
37 The contents are validated (for well-formedness) by NetworkPkg/HttpDxe.
46 FIRMWARE_CONFIG_ITEM HttpsCaCertsItem
;
47 UINTN HttpsCaCertsSize
;
50 Status
= QemuFwCfgFindFile ("etc/edk2/https/cacerts", &HttpsCaCertsItem
,
52 if (EFI_ERROR (Status
)) {
53 DEBUG ((DEBUG_VERBOSE
, "%a:%a: not touching CA cert list\n",
54 gEfiCallerBaseName
, __FUNCTION__
));
59 // Delete the current EFI_TLS_CA_CERTIFICATE_VARIABLE if it exists. This
60 // serves two purposes:
62 // (a) If the variable exists with EFI_VARIABLE_NON_VOLATILE attribute, we
63 // cannot make it volatile without deleting it first.
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.
70 Status
= gRT
->SetVariable (
71 EFI_TLS_CA_CERTIFICATE_VARIABLE
, // VariableName
72 &gEfiTlsCaCertificateGuid
, // VendorGuid
77 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
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
);
88 if (HttpsCaCertsSize
== 0) {
89 DEBUG ((DEBUG_VERBOSE
, "%a:%a: applied empty CA cert list\n",
90 gEfiCallerBaseName
, __FUNCTION__
));
94 HttpsCaCerts
= AllocatePool (HttpsCaCertsSize
);
95 if (HttpsCaCerts
== NULL
) {
96 DEBUG ((DEBUG_ERROR
, "%a:%a: failed to allocate HttpsCaCerts\n",
97 gEfiCallerBaseName
, __FUNCTION__
));
101 QemuFwCfgSelectItem (HttpsCaCertsItem
);
102 QemuFwCfgReadBytes (HttpsCaCertsSize
, HttpsCaCerts
);
104 Status
= gRT
->SetVariable (
105 EFI_TLS_CA_CERTIFICATE_VARIABLE
, // VariableName
106 &gEfiTlsCaCertificateGuid
, // VendorGuid
107 EFI_VARIABLE_BOOTSERVICE_ACCESS
, // Attributes
108 HttpsCaCertsSize
, // DataSize
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
;
118 DEBUG ((DEBUG_VERBOSE
, "%a:%a: stored CA cert list (%Lu byte(s))\n",
119 gEfiCallerBaseName
, __FUNCTION__
, (UINT64
)HttpsCaCertsSize
));
122 FreePool (HttpsCaCerts
);
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.
130 The contents are propagated by NetworkPkg/HttpDxe to NetworkPkg/TlsDxe; the
131 list is processed by the latter.
140 FIRMWARE_CONFIG_ITEM HttpsCiphersItem
;
141 UINTN HttpsCiphersSize
;
144 Status
= QemuFwCfgFindFile ("etc/edk2/https/ciphers", &HttpsCiphersItem
,
146 if (EFI_ERROR (Status
)) {
147 DEBUG ((DEBUG_VERBOSE
, "%a:%a: not touching cipher suites\n",
148 gEfiCallerBaseName
, __FUNCTION__
));
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.
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.
162 Status
= gRT
->SetVariable (
163 EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE
, // VariableName
164 &gEdkiiHttpTlsCipherListGuid
, // VendorGuid
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
));
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
;
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
;
191 QemuFwCfgSelectItem (HttpsCiphersItem
);
192 QemuFwCfgReadBytes (HttpsCiphersSize
, HttpsCiphers
);
194 Status
= gRT
->SetVariable (
195 EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE
, // VariableName
196 &gEdkiiHttpTlsCipherListGuid
, // VendorGuid
197 EFI_VARIABLE_BOOTSERVICE_ACCESS
, // Attributes
198 HttpsCiphersSize
, // DataSize
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
;
208 DEBUG ((DEBUG_VERBOSE
, "%a:%a: stored list of cipher suites (%Lu byte(s))\n",
209 gEfiCallerBaseName
, __FUNCTION__
, (UINT64
)HttpsCiphersSize
));
212 FreePool (HttpsCiphers
);
215 if (EFI_ERROR (Status
)) {
216 ASSERT_EFI_ERROR (Status
);
230 return RETURN_SUCCESS
;