]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.c
OvmfPkg/TlsAuthConfigLib: configure trusted CA certs for HTTPS boot
[mirror_edk2.git] / OvmfPkg / Library / TlsAuthConfigLib / TlsAuthConfigLib.c
diff --git a/OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.c b/OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.c
new file mode 100644 (file)
index 0000000..b5b33bc
--- /dev/null
@@ -0,0 +1,133 @@
+/** @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