Introduce TlsAuthConfigLib to read the list of trusted CA certificates
from fw_cfg and to store it to EFI_TLS_CA_CERTIFICATE_VARIABLE.
The fw_cfg file is formatted by the "p11-kit" and "update-ca-trust"
utilities on the host side, so that the host settings take effect in guest
HTTPS boot as well. QEMU forwards the file intact to the firmware. The
contents are sanity-checked by NetworkPkg/HttpDxe code that was added in
commit
0fd13678a681.
Link TlsAuthConfigLib via NULL resolution into TlsAuthConfigDxe. This sets
EFI_TLS_CA_CERTIFICATE_VARIABLE in time for both
NetworkPkg/TlsAuthConfigDxe (for possible HII interaction with the user)
and for NetworkPkg/HttpDxe (for the effective TLS configuration).
The file formatted by "p11-kit" can be large. On a RHEL-7 host, the the
Mozilla CA root certificate bundle -- installed with the "ca-certificates"
package -- is processed into a 182KB file. Thus, create
EFI_TLS_CA_CERTIFICATE_VARIABLE as a volatile & boot-time only variable.
Also, in TLS_ENABLE builds, set the cumulative limit for volatile
variables (PcdVariableStoreSize) to 512KB, and the individual limit for
the same (PcdMaxVolatileVariableSize) to 256KB.
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Gary Ching-Pang Lin <glin@suse.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Gary Lin <glin@suse.com>
Tested-by: Gary Lin <glin@suse.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
--- /dev/null
+/** @file\r
+\r
+ A hook-in library for NetworkPkg/TlsAuthConfigDxe, in order to set volatile\r
+ variables related to TLS configuration, before TlsAuthConfigDxe or HttpDxe\r
+ (which is a UEFI_DRIVER) consume them.\r
+\r
+ Copyright (C) 2013, 2015, 2018, Red Hat, Inc.\r
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi/UefiBaseType.h>\r
+#include <Uefi/UefiSpec.h>\r
+\r
+#include <Guid/TlsAuthentication.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+\r
+/**\r
+ Read the list of trusted CA certificates from the fw_cfg file\r
+ "etc/edk2/https/cacerts", and store it to\r
+ gEfiTlsCaCertificateGuid:EFI_TLS_CA_CERTIFICATE_VARIABLE.\r
+\r
+ The contents are validated (for well-formedness) by NetworkPkg/HttpDxe.\r
+**/\r
+STATIC\r
+VOID\r
+SetCaCerts (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ FIRMWARE_CONFIG_ITEM HttpsCaCertsItem;\r
+ UINTN HttpsCaCertsSize;\r
+ VOID *HttpsCaCerts;\r
+\r
+ Status = QemuFwCfgFindFile ("etc/edk2/https/cacerts", &HttpsCaCertsItem,\r
+ &HttpsCaCertsSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_VERBOSE, "%a:%a: not touching CA cert list\n",\r
+ gEfiCallerBaseName, __FUNCTION__));\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Delete the current EFI_TLS_CA_CERTIFICATE_VARIABLE if it exists. This\r
+ // serves two purposes:\r
+ //\r
+ // (a) If the variable exists with EFI_VARIABLE_NON_VOLATILE attribute, we\r
+ // cannot make it volatile without deleting it first.\r
+ //\r
+ // (b) If we fail to recreate the variable later, deleting the current one is\r
+ // still justified if the fw_cfg file exists. Emptying the set of trusted\r
+ // CA certificates will fail HTTPS boot, which is better than trusting\r
+ // any certificate that's possibly missing from the fw_cfg file.\r
+ //\r
+ Status = gRT->SetVariable (\r
+ EFI_TLS_CA_CERTIFICATE_VARIABLE, // VariableName\r
+ &gEfiTlsCaCertificateGuid, // VendorGuid\r
+ 0, // Attributes\r
+ 0, // DataSize\r
+ NULL // Data\r
+ );\r
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
+ //\r
+ // This is fatal.\r
+ //\r
+ DEBUG ((DEBUG_ERROR, "%a:%a: failed to delete %g:\"%s\"\n",\r
+ gEfiCallerBaseName, __FUNCTION__, &gEfiTlsCaCertificateGuid,\r
+ EFI_TLS_CA_CERTIFICATE_VARIABLE));\r
+ ASSERT_EFI_ERROR (Status);\r
+ CpuDeadLoop ();\r
+ }\r
+\r
+ if (HttpsCaCertsSize == 0) {\r
+ DEBUG ((DEBUG_VERBOSE, "%a:%a: applied empty CA cert list\n",\r
+ gEfiCallerBaseName, __FUNCTION__));\r
+ return;\r
+ }\r
+\r
+ HttpsCaCerts = AllocatePool (HttpsCaCertsSize);\r
+ if (HttpsCaCerts == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "%a:%a: failed to allocate HttpsCaCerts\n",\r
+ gEfiCallerBaseName, __FUNCTION__));\r
+ return;\r
+ }\r
+\r
+ QemuFwCfgSelectItem (HttpsCaCertsItem);\r
+ QemuFwCfgReadBytes (HttpsCaCertsSize, HttpsCaCerts);\r
+\r
+ Status = gRT->SetVariable (\r
+ EFI_TLS_CA_CERTIFICATE_VARIABLE, // VariableName\r
+ &gEfiTlsCaCertificateGuid, // VendorGuid\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS, // Attributes\r
+ HttpsCaCertsSize, // DataSize\r
+ HttpsCaCerts // Data\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a:%a: failed to set %g:\"%s\": %r\n",\r
+ gEfiCallerBaseName, __FUNCTION__, &gEfiTlsCaCertificateGuid,\r
+ EFI_TLS_CA_CERTIFICATE_VARIABLE, Status));\r
+ goto FreeHttpsCaCerts;\r
+ }\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "%a:%a: stored CA cert list (%Lu byte(s))\n",\r
+ gEfiCallerBaseName, __FUNCTION__, (UINT64)HttpsCaCertsSize));\r
+\r
+FreeHttpsCaCerts:\r
+ FreePool (HttpsCaCerts);\r
+}\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+TlsAuthConfigInit (\r
+ VOID\r
+ )\r
+{\r
+ SetCaCerts ();\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
--- /dev/null
+## @file\r
+#\r
+# A hook-in library for NetworkPkg/TlsAuthConfigDxe, in order to set volatile\r
+# variables related to TLS configuration, before TlsAuthConfigDxe or HttpDxe\r
+# (which is a UEFI_DRIVER) consume them.\r
+#\r
+# Copyright (C) 2013, 2015, 2018, Red Hat, Inc.\r
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are licensed and made available\r
+# under the terms and conditions of the BSD License which accompanies this\r
+# distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 1.26\r
+ BASE_NAME = TlsAuthConfigLib\r
+ FILE_GUID = 660AB627-4C5F-4D42-A3B6-BD021E9028BD\r
+ MODULE_TYPE = BASE\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = TlsAuthConfigLib|DXE_DRIVER\r
+ CONSTRUCTOR = TlsAuthConfigInit\r
+\r
+#\r
+# The following information is for reference only and not required by the build\r
+# tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64\r
+#\r
+\r
+[Sources]\r
+ TlsAuthConfigLib.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ NetworkPkg/NetworkPkg.dec\r
+ OvmfPkg/OvmfPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ DebugLib\r
+ MemoryAllocationLib\r
+ QemuFwCfgLib\r
+ UefiRuntimeServicesTableLib\r
+\r
+[Guids]\r
+ gEfiTlsCaCertificateGuid ## PRODUCES ## Variable:L"TlsCaCertificate"\r
+\r
+[Depex]\r
+ gEfiVariableWriteArchProtocolGuid\r
!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800\r
+!if $(TLS_ENABLE) == FALSE\r
# match PcdFlashNvStorageVariableSize purely for convenience\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000\r
!endif\r
+!endif\r
!if $(FD_SIZE_IN_KB) == 4096\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400\r
+!if $(TLS_ENABLE) == FALSE\r
# match PcdFlashNvStorageVariableSize purely for convenience\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000\r
!endif\r
+!endif\r
+!if $(TLS_ENABLE) == TRUE\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x80000\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize|0x40000\r
+!endif\r
\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0\r
\r
!endif\r
!if $(TLS_ENABLE) == TRUE\r
NetworkPkg/TlsDxe/TlsDxe.inf\r
- NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf\r
+ NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf {\r
+ <LibraryClasses>\r
+ NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf\r
+ }\r
!endif\r
OvmfPkg/VirtioNetDxe/VirtioNet.inf\r
\r
!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800\r
+!if $(TLS_ENABLE) == FALSE\r
# match PcdFlashNvStorageVariableSize purely for convenience\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000\r
!endif\r
+!endif\r
!if $(FD_SIZE_IN_KB) == 4096\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400\r
+!if $(TLS_ENABLE) == FALSE\r
# match PcdFlashNvStorageVariableSize purely for convenience\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000\r
!endif\r
+!endif\r
+!if $(TLS_ENABLE) == TRUE\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x80000\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize|0x40000\r
+!endif\r
\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0\r
\r
!endif\r
!if $(TLS_ENABLE) == TRUE\r
NetworkPkg/TlsDxe/TlsDxe.inf\r
- NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf\r
+ NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf {\r
+ <LibraryClasses>\r
+ NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf\r
+ }\r
!endif\r
OvmfPkg/VirtioNetDxe/VirtioNet.inf\r
\r
!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800\r
+!if $(TLS_ENABLE) == FALSE\r
# match PcdFlashNvStorageVariableSize purely for convenience\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000\r
!endif\r
+!endif\r
!if $(FD_SIZE_IN_KB) == 4096\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400\r
+!if $(TLS_ENABLE) == FALSE\r
# match PcdFlashNvStorageVariableSize purely for convenience\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000\r
!endif\r
+!endif\r
+!if $(TLS_ENABLE) == TRUE\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x80000\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize|0x40000\r
+!endif\r
\r
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0\r
\r
!endif\r
!if $(TLS_ENABLE) == TRUE\r
NetworkPkg/TlsDxe/TlsDxe.inf\r
- NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf\r
+ NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf {\r
+ <LibraryClasses>\r
+ NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf\r
+ }\r
!endif\r
OvmfPkg/VirtioNetDxe/VirtioNet.inf\r
\r