+/** @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