2018-03-28 03:04:06 +02:00
|
|
|
/** @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.<BR>
|
|
|
|
|
2019-04-04 01:06:33 +02:00
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
2018-03-28 03:04:06 +02:00
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include <Uefi/UefiBaseType.h>
|
|
|
|
#include <Uefi/UefiSpec.h>
|
|
|
|
|
2018-04-01 01:27:43 +02:00
|
|
|
#include <Guid/HttpTlsCipherList.h>
|
2018-03-28 03:04:06 +02:00
|
|
|
#include <Guid/TlsAuthentication.h>
|
|
|
|
|
|
|
|
#include <Library/BaseLib.h>
|
|
|
|
#include <Library/DebugLib.h>
|
|
|
|
#include <Library/MemoryAllocationLib.h>
|
|
|
|
#include <Library/QemuFwCfgLib.h>
|
|
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
|
|
|
|
|
|
/**
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-04-01 01:27:43 +02:00
|
|
|
/**
|
|
|
|
Read the list of trusted cipher suites from the fw_cfg file
|
|
|
|
"etc/edk2/https/ciphers", and store it to
|
|
|
|
gEdkiiHttpTlsCipherListGuid:EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE.
|
|
|
|
|
|
|
|
The contents are propagated by NetworkPkg/HttpDxe to NetworkPkg/TlsDxe; the
|
|
|
|
list is processed by the latter.
|
|
|
|
**/
|
|
|
|
STATIC
|
|
|
|
VOID
|
|
|
|
SetCipherSuites (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
FIRMWARE_CONFIG_ITEM HttpsCiphersItem;
|
|
|
|
UINTN HttpsCiphersSize;
|
|
|
|
VOID *HttpsCiphers;
|
|
|
|
|
|
|
|
Status = QemuFwCfgFindFile ("etc/edk2/https/ciphers", &HttpsCiphersItem,
|
|
|
|
&HttpsCiphersSize);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "%a:%a: not touching cipher suites\n",
|
|
|
|
gEfiCallerBaseName, __FUNCTION__));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// From this point on, any failure is fatal. An ordered cipher preference
|
|
|
|
// list is available from QEMU, thus we cannot let the firmware attempt HTTPS
|
|
|
|
// boot with either pre-existent or non-existent preferences. An empty set of
|
|
|
|
// cipher suites does not fail HTTPS boot automatically; the default cipher
|
|
|
|
// suite preferences would take effect, and we must prevent that.
|
|
|
|
//
|
|
|
|
// Delete the current EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE if it exists. If
|
|
|
|
// the variable exists with EFI_VARIABLE_NON_VOLATILE attribute, we cannot
|
|
|
|
// make it volatile without deleting it first.
|
|
|
|
//
|
|
|
|
Status = gRT->SetVariable (
|
|
|
|
EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE, // VariableName
|
|
|
|
&gEdkiiHttpTlsCipherListGuid, // VendorGuid
|
|
|
|
0, // Attributes
|
|
|
|
0, // DataSize
|
|
|
|
NULL // Data
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
|
|
|
|
DEBUG ((DEBUG_ERROR, "%a:%a: failed to delete %g:\"%s\"\n",
|
|
|
|
gEfiCallerBaseName, __FUNCTION__, &gEdkiiHttpTlsCipherListGuid,
|
|
|
|
EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE));
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (HttpsCiphersSize == 0) {
|
|
|
|
DEBUG ((DEBUG_ERROR, "%a:%a: list of cipher suites must not be empty\n",
|
|
|
|
gEfiCallerBaseName, __FUNCTION__));
|
|
|
|
Status = EFI_INVALID_PARAMETER;
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
HttpsCiphers = AllocatePool (HttpsCiphersSize);
|
|
|
|
if (HttpsCiphers == NULL) {
|
|
|
|
DEBUG ((DEBUG_ERROR, "%a:%a: failed to allocate HttpsCiphers\n",
|
|
|
|
gEfiCallerBaseName, __FUNCTION__));
|
|
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
|
|
goto Done;
|
|
|
|
}
|
|
|
|
|
|
|
|
QemuFwCfgSelectItem (HttpsCiphersItem);
|
|
|
|
QemuFwCfgReadBytes (HttpsCiphersSize, HttpsCiphers);
|
|
|
|
|
|
|
|
Status = gRT->SetVariable (
|
|
|
|
EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE, // VariableName
|
|
|
|
&gEdkiiHttpTlsCipherListGuid, // VendorGuid
|
|
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS, // Attributes
|
|
|
|
HttpsCiphersSize, // DataSize
|
|
|
|
HttpsCiphers // Data
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
DEBUG ((DEBUG_ERROR, "%a:%a: failed to set %g:\"%s\"\n",
|
|
|
|
gEfiCallerBaseName, __FUNCTION__, &gEdkiiHttpTlsCipherListGuid,
|
|
|
|
EDKII_HTTP_TLS_CIPHER_LIST_VARIABLE));
|
|
|
|
goto FreeHttpsCiphers;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "%a:%a: stored list of cipher suites (%Lu byte(s))\n",
|
|
|
|
gEfiCallerBaseName, __FUNCTION__, (UINT64)HttpsCiphersSize));
|
|
|
|
|
|
|
|
FreeHttpsCiphers:
|
|
|
|
FreePool (HttpsCiphers);
|
|
|
|
|
|
|
|
Done:
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
CpuDeadLoop ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-28 03:04:06 +02:00
|
|
|
RETURN_STATUS
|
|
|
|
EFIAPI
|
|
|
|
TlsAuthConfigInit (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
SetCaCerts ();
|
2018-04-01 01:27:43 +02:00
|
|
|
SetCipherSuites ();
|
2018-03-28 03:04:06 +02:00
|
|
|
|
|
|
|
return RETURN_SUCCESS;
|
|
|
|
}
|