From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=lersek@redhat.com; receiver=edk2-devel@lists.01.org Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id C0711224DD124 for ; Wed, 28 Mar 2018 13:20:22 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 208A640572A1; Wed, 28 Mar 2018 20:27:01 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-120-75.rdu2.redhat.com [10.10.120.75]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3B8A210B2B26; Wed, 28 Mar 2018 20:27:00 +0000 (UTC) From: Laszlo Ersek To: edk2-devel-01 Cc: Ard Biesheuvel , Gary Ching-Pang Lin , Jordan Justen Date: Wed, 28 Mar 2018 22:26:51 +0200 Message-Id: <20180328202651.1478-5-lersek@redhat.com> In-Reply-To: <20180328202651.1478-1-lersek@redhat.com> References: <20180328202651.1478-1-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Wed, 28 Mar 2018 20:27:01 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Wed, 28 Mar 2018 20:27:01 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'lersek@redhat.com' RCPT:'' Subject: [PATCH 4/4] OvmfPkg/TlsAuthConfigLib: configure trusted CA certs for HTTPS boot X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 Mar 2018 20:20:23 -0000 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 Cc: Gary Ching-Pang Lin Cc: Jordan Justen Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Laszlo Ersek --- OvmfPkg/OvmfPkgIa32.dsc | 13 +- OvmfPkg/OvmfPkgIa32X64.dsc | 13 +- OvmfPkg/OvmfPkgX64.dsc | 13 +- OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf | 55 ++++++++ OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.c | 133 ++++++++++++++++++++ 5 files changed, 224 insertions(+), 3 deletions(-) diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 7664b50ddef9..c9eb248506c5 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -439,15 +439,23 @@ [PcdsFixedAtBuild] !if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 +!if $(TLS_ENABLE) == FALSE # match PcdFlashNvStorageVariableSize purely for convenience gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000 !endif +!endif !if $(FD_SIZE_IN_KB) == 4096 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400 +!if $(TLS_ENABLE) == FALSE # match PcdFlashNvStorageVariableSize purely for convenience gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000 !endif +!endif +!if $(TLS_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x80000 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize|0x40000 +!endif gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0 @@ -796,7 +804,10 @@ [Components] !endif !if $(TLS_ENABLE) == TRUE NetworkPkg/TlsDxe/TlsDxe.inf - NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf + NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf { + + NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf + } !endif OvmfPkg/VirtioNetDxe/VirtioNet.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index e5969090d437..17aef2d4830f 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -444,15 +444,23 @@ [PcdsFixedAtBuild] !if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 +!if $(TLS_ENABLE) == FALSE # match PcdFlashNvStorageVariableSize purely for convenience gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000 !endif +!endif !if $(FD_SIZE_IN_KB) == 4096 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400 +!if $(TLS_ENABLE) == FALSE # match PcdFlashNvStorageVariableSize purely for convenience gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000 !endif +!endif +!if $(TLS_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x80000 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize|0x40000 +!endif gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0 @@ -805,7 +813,10 @@ [Components.X64] !endif !if $(TLS_ENABLE) == TRUE NetworkPkg/TlsDxe/TlsDxe.inf - NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf + NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf { + + NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf + } !endif OvmfPkg/VirtioNetDxe/VirtioNet.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 7197c1984a7c..8af763ea9e9e 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -444,15 +444,23 @@ [PcdsFixedAtBuild] !if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048) gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 +!if $(TLS_ENABLE) == FALSE # match PcdFlashNvStorageVariableSize purely for convenience gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000 !endif +!endif !if $(FD_SIZE_IN_KB) == 4096 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400 +!if $(TLS_ENABLE) == FALSE # match PcdFlashNvStorageVariableSize purely for convenience gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000 !endif +!endif +!if $(TLS_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x80000 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize|0x40000 +!endif gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0 @@ -803,7 +811,10 @@ [Components] !endif !if $(TLS_ENABLE) == TRUE NetworkPkg/TlsDxe/TlsDxe.inf - NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf + NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf { + + NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf + } !endif OvmfPkg/VirtioNetDxe/VirtioNet.inf diff --git a/OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf b/OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf new file mode 100644 index 000000000000..5f83582a8313 --- /dev/null +++ b/OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf @@ -0,0 +1,55 @@ +## @file +# +# A hook-in library for NetworkPkg/TlsAuthConfigDxe, in order to set volatile +# variables related to TLS configuration, before TlsAuthConfigDxe or HttpDxe +# (which is a UEFI_DRIVER) consume them. +# +# Copyright (C) 2013, 2015, 2018, Red Hat, Inc. +# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT +# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 1.26 + BASE_NAME = TlsAuthConfigLib + FILE_GUID = 660AB627-4C5F-4D42-A3B6-BD021E9028BD + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TlsAuthConfigLib|DXE_DRIVER + CONSTRUCTOR = TlsAuthConfigInit + +# +# The following information is for reference only and not required by the build +# tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + TlsAuthConfigLib.c + +[Packages] + MdePkg/MdePkg.dec + NetworkPkg/NetworkPkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + MemoryAllocationLib + QemuFwCfgLib + UefiRuntimeServicesTableLib + +[Guids] + gEfiTlsCaCertificateGuid ## PRODUCES ## Variable:L"TlsCaCertificate" + +[Depex] + gEfiVariableWriteArchProtocolGuid diff --git a/OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.c b/OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.c new file mode 100644 index 000000000000..b5b33bc4fc69 --- /dev/null +++ b/OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.c @@ -0,0 +1,133 @@ +/** @file + + A hook-in library for NetworkPkg/TlsAuthConfigDxe, in order to set volatile + variables related to TLS configuration, before TlsAuthConfigDxe or HttpDxe + (which is a UEFI_DRIVER) consume them. + + Copyright (C) 2013, 2015, 2018, Red Hat, Inc. + Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +/** + Read the list of trusted CA certificates from the fw_cfg file + "etc/edk2/https/cacerts", and store it to + gEfiTlsCaCertificateGuid:EFI_TLS_CA_CERTIFICATE_VARIABLE. + + The contents are validated (for well-formedness) by NetworkPkg/HttpDxe. +**/ +STATIC +VOID +SetCaCerts ( + VOID + ) +{ + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM HttpsCaCertsItem; + UINTN HttpsCaCertsSize; + VOID *HttpsCaCerts; + + Status = QemuFwCfgFindFile ("etc/edk2/https/cacerts", &HttpsCaCertsItem, + &HttpsCaCertsSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_VERBOSE, "%a:%a: not touching CA cert list\n", + gEfiCallerBaseName, __FUNCTION__)); + return; + } + + // + // Delete the current EFI_TLS_CA_CERTIFICATE_VARIABLE if it exists. This + // serves two purposes: + // + // (a) If the variable exists with EFI_VARIABLE_NON_VOLATILE attribute, we + // cannot make it volatile without deleting it first. + // + // (b) If we fail to recreate the variable later, deleting the current one is + // still justified if the fw_cfg file exists. Emptying the set of trusted + // CA certificates will fail HTTPS boot, which is better than trusting + // any certificate that's possibly missing from the fw_cfg file. + // + Status = gRT->SetVariable ( + EFI_TLS_CA_CERTIFICATE_VARIABLE, // VariableName + &gEfiTlsCaCertificateGuid, // VendorGuid + 0, // Attributes + 0, // DataSize + NULL // Data + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + // + // This is fatal. + // + DEBUG ((DEBUG_ERROR, "%a:%a: failed to delete %g:\"%s\"\n", + gEfiCallerBaseName, __FUNCTION__, &gEfiTlsCaCertificateGuid, + EFI_TLS_CA_CERTIFICATE_VARIABLE)); + ASSERT_EFI_ERROR (Status); + CpuDeadLoop (); + } + + if (HttpsCaCertsSize == 0) { + DEBUG ((DEBUG_VERBOSE, "%a:%a: applied empty CA cert list\n", + gEfiCallerBaseName, __FUNCTION__)); + return; + } + + HttpsCaCerts = AllocatePool (HttpsCaCertsSize); + if (HttpsCaCerts == NULL) { + DEBUG ((DEBUG_ERROR, "%a:%a: failed to allocate HttpsCaCerts\n", + gEfiCallerBaseName, __FUNCTION__)); + return; + } + + QemuFwCfgSelectItem (HttpsCaCertsItem); + QemuFwCfgReadBytes (HttpsCaCertsSize, HttpsCaCerts); + + Status = gRT->SetVariable ( + EFI_TLS_CA_CERTIFICATE_VARIABLE, // VariableName + &gEfiTlsCaCertificateGuid, // VendorGuid + EFI_VARIABLE_BOOTSERVICE_ACCESS, // Attributes + HttpsCaCertsSize, // DataSize + HttpsCaCerts // Data + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a:%a: failed to set %g:\"%s\": %r\n", + gEfiCallerBaseName, __FUNCTION__, &gEfiTlsCaCertificateGuid, + EFI_TLS_CA_CERTIFICATE_VARIABLE, Status)); + goto FreeHttpsCaCerts; + } + + DEBUG ((DEBUG_VERBOSE, "%a:%a: stored CA cert list (%Lu byte(s))\n", + gEfiCallerBaseName, __FUNCTION__, (UINT64)HttpsCaCertsSize)); + +FreeHttpsCaCerts: + FreePool (HttpsCaCerts); +} + +RETURN_STATUS +EFIAPI +TlsAuthConfigInit ( + VOID + ) +{ + SetCaCerts (); + + return RETURN_SUCCESS; +} -- 2.14.1.3.gb7cf6e02401b