summaryrefslogtreecommitdiffstats
path: root/src/VBox/Runtime/common/efi/efisignaturedb.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
commit16f504a9dca3fe3b70568f67b7d41241ae485288 (patch)
treec60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Runtime/common/efi/efisignaturedb.cpp
parentInitial commit. (diff)
downloadvirtualbox-upstream.tar.xz
virtualbox-upstream.zip
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Runtime/common/efi/efisignaturedb.cpp')
-rw-r--r--src/VBox/Runtime/common/efi/efisignaturedb.cpp587
1 files changed, 587 insertions, 0 deletions
diff --git a/src/VBox/Runtime/common/efi/efisignaturedb.cpp b/src/VBox/Runtime/common/efi/efisignaturedb.cpp
new file mode 100644
index 00000000..6f9c3436
--- /dev/null
+++ b/src/VBox/Runtime/common/efi/efisignaturedb.cpp
@@ -0,0 +1,587 @@
+/* $Id: efisignaturedb.cpp $ */
+/** @file
+ * IPRT - EFI signature database helpers.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_DEFAULT
+#include <iprt/efi.h>
+
+#include <iprt/cdefs.h>
+#include <iprt/asm.h>
+#include <iprt/string.h>
+#include <iprt/list.h>
+#include <iprt/mem.h>
+#include <iprt/sg.h>
+
+#include <iprt/formats/efi-signature.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+/**
+ * EFI signature entry.
+ */
+typedef struct RTEFISIGNATURE
+{
+ /** List node. */
+ RTLISTNODE NdLst;
+ /** The signature owner. */
+ RTUUID UuidOwner;
+ /** Size of the signature data in bytes. */
+ uint32_t cbSignature;
+ /** The signature data (variable in size). */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abSignature[RT_FLEXIBLE_ARRAY];
+} RTEFISIGNATURE;
+/** Pointer to a EFI signature entry. */
+typedef RTEFISIGNATURE *PRTEFISIGNATURE;
+/** Pointer to a const EFI signature entry. */
+typedef const RTEFISIGNATURE *PCRTEFISIGNATURE;
+
+
+/**
+ * The EFI signature database instance data.
+ */
+typedef struct RTEFISIGDBINT
+{
+ /** List head of the various signature types. */
+ RTLISTANCHOR aLstSigTypes[RTEFISIGTYPE_FIRST_INVALID];
+} RTEFISIGDBINT;
+/** Pointer to the EFI signature database instance data. */
+typedef RTEFISIGDBINT *PRTEFISIGDBINT;
+
+
+/**
+ * Signature type descriptor.
+ */
+typedef struct RTEFISIGDBDESC
+{
+ /** The EFI GUID identifying the signature type. */
+ EFI_GUID GuidSignatureType;
+ /** The additional signature header for this signature type. */
+ uint32_t cbSigHdr;
+ /** Size of the signature data (including EFI_SIGNATURE_DATA),
+ * can be 0 size varies with each signature (X.509 for example). */
+ uint32_t cbSig;
+ /** The internal signature type enum. */
+ RTEFISIGTYPE enmSigType;
+ /** Human readable string of the signature type. */
+ const char *pszName;
+} RTEFISIGDBDESC;
+/** Pointer to a signature type descriptor. */
+typedef RTEFISIGDBDESC *PRTEFISIGDBDESC;
+/** Pointer to a const signature type descriptor. */
+typedef const RTEFISIGDBDESC *PCRTEFISIGDBDESC;
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+
+/**
+ * Mapping of EFI signature GUIDs to their IPRT signature type equivalent.
+ */
+static const RTEFISIGDBDESC g_aGuid2SigTypeMapping[] =
+{
+ { EFI_NULL_GUID, 0, 0, RTEFISIGTYPE_INVALID, "INVALID" },
+ { EFI_SIGNATURE_TYPE_GUID_SHA256, 0, EFI_SIGNATURE_TYPE_SZ_SHA256, RTEFISIGTYPE_SHA256, "SHA-256" },
+ { EFI_SIGNATURE_TYPE_GUID_RSA2048, 0, EFI_SIGNATURE_TYPE_SZ_RSA2048, RTEFISIGTYPE_RSA2048, "RSA-2048" },
+ { EFI_SIGNATURE_TYPE_GUID_RSA2048_SHA256, 0, EFI_SIGNATURE_TYPE_SZ_RSA2048_SHA256, RTEFISIGTYPE_RSA2048_SHA256, "RSA-2048/SHA-256" },
+ { EFI_SIGNATURE_TYPE_GUID_SHA1, 0, EFI_SIGNATURE_TYPE_SZ_SHA1, RTEFISIGTYPE_SHA1, "SHA-1" },
+ { EFI_SIGNATURE_TYPE_GUID_RSA2048_SHA1, 0, EFI_SIGNATURE_TYPE_SZ_RSA2048_SHA1, RTEFISIGTYPE_RSA2048_SHA1, "RSA-2048/SHA-1" },
+ { EFI_SIGNATURE_TYPE_GUID_X509, 0, 0, RTEFISIGTYPE_X509, "X.509" }
+};
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+
+
+/**
+ * Returns the internal siganture type descriptor for the given EFI GUID.
+ *
+ * @returns Pointer to the descriptor if found or NULL if not.
+ * @param pGuid The EFI signature type GUID to look for.
+ */
+static PCRTEFISIGDBDESC rtEfiSigDbGetDescByGuid(PCEFI_GUID pGuid)
+{
+ for (uint32_t i = 0; i < RT_ELEMENTS(g_aGuid2SigTypeMapping); i++)
+ if (!RTEfiGuidCompare(&g_aGuid2SigTypeMapping[i].GuidSignatureType, pGuid))
+ return &g_aGuid2SigTypeMapping[i];
+
+ return NULL;
+}
+
+
+/**
+ * Validates the given signature lsit header.
+ *
+ * @returns Flag whether the list header is considered valid.
+ * @param pLstHdr The list header to validate.
+ * @param pDesc The descriptor for the signature type of the given list.
+ */
+static bool rtEfiSigDbSigHdrValidate(PCEFI_SIGNATURE_LIST pLstHdr, PCRTEFISIGDBDESC pDesc)
+{
+ uint32_t cbSigLst = RT_LE2H_U32(pLstHdr->cbSigLst);
+ uint32_t cbSigHdr = RT_LE2H_U32(pLstHdr->cbSigHdr);
+ uint32_t cbSig = RT_LE2H_U32(pLstHdr->cbSig);
+
+ if (cbSigHdr != pDesc->cbSigHdr)
+ return false;
+ if (cbSig < sizeof(EFI_SIGNATURE_DATA))
+ return false;
+ if ( pDesc->cbSig
+ && pLstHdr->cbSig != pDesc->cbSig)
+ return false;
+ if ( cbSigLst <= sizeof(*pLstHdr)
+ || cbSigLst <= cbSigHdr
+ || cbSigLst <= cbSig)
+ return false;
+ if ((cbSigLst - sizeof(*pLstHdr) - cbSigHdr) % cbSig)
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Loads a single signature list into the given signature database from the given file.
+ *
+ * @returns IPRT status code.
+ * @param pThis The signature database instance.
+ * @param hVfsFileIn The file to load the signature list from.
+ * @param pcbConsumed Where to store the number of bytes consumed for this signature list on success.
+ */
+static int rtEfiSigDbLoadSigList(PRTEFISIGDBINT pThis, RTVFSFILE hVfsFileIn, uint64_t *pcbConsumed)
+{
+ EFI_SIGNATURE_LIST LstHdr;
+ int rc = RTVfsFileRead(hVfsFileIn, &LstHdr, sizeof(LstHdr), NULL /*pcbRead*/);
+ if (RT_SUCCESS(rc))
+ {
+ PCRTEFISIGDBDESC pDesc = rtEfiSigDbGetDescByGuid(&LstHdr.GuidSigType);
+ if (pDesc)
+ {
+ if (rtEfiSigDbSigHdrValidate(&LstHdr, pDesc))
+ {
+ RTLISTANCHOR LstTmp;
+ uint32_t cbSig = RT_LE2H_U32(LstHdr.cbSig);
+ uint32_t cbSigData = cbSig - sizeof(EFI_SIGNATURE_DATA);
+ uint32_t cSigs = (RT_LE2H_U32(LstHdr.cbSigLst) - RT_LE2H_U32(LstHdr.cbSigHdr)) / cbSig;
+
+ /** @todo Skip/parse signature header if we have to add a type which has this != 0. */
+ RTListInit(&LstTmp);
+ for (uint32_t i = 0; i < cSigs && RT_SUCCESS(rc); i++)
+ {
+ PRTEFISIGNATURE pSig = (PRTEFISIGNATURE)RTMemAllocZ(RT_UOFFSETOF_DYN(RTEFISIGNATURE, abSignature[cbSigData]));
+ if (pSig)
+ {
+ EFI_SIGNATURE_DATA SigData;
+ rc = RTVfsFileRead(hVfsFileIn, &SigData, sizeof(SigData), NULL /*pcbRead*/);
+ if (RT_SUCCESS(rc))
+ rc = RTVfsFileRead(hVfsFileIn, &pSig->abSignature[0], cbSigData, NULL /*pcbRead*/);
+ if (RT_SUCCESS(rc))
+ {
+ RTEfiGuidToUuid(&pSig->UuidOwner, &SigData.GuidOwner);
+ pSig->cbSignature = cbSigData;
+ RTListAppend(&LstTmp, &pSig->NdLst);
+ }
+ else
+ RTMemFree(pSig);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ /* Add the signatures to the list. */
+ RTListConcatenate(&pThis->aLstSigTypes[pDesc->enmSigType], &LstTmp);
+ *pcbConsumed = sizeof(LstHdr) + RT_LE2H_U32(LstHdr.cbSigHdr) + cSigs * cbSig;
+ }
+ else
+ {
+ /* Destroy the temporary list. */
+ PRTEFISIGNATURE pIt, pItNext;
+
+ RTListForEachSafe(&LstTmp, pIt, pItNext, RTEFISIGNATURE, NdLst)
+ {
+ RTListNodeRemove(&pIt->NdLst);
+ RTMemFree(pIt);
+ }
+ }
+ }
+ else
+ rc = VERR_NOT_SUPPORTED;
+ }
+ else
+ rc = VERR_NOT_SUPPORTED;
+ }
+
+ return rc;
+}
+
+
+/**
+ * Variant for written a list of signatures where each signature gets its own signature list header
+ * (for types where each signature can differ in size like X.509).
+ *
+ * @returns IPRT status code.
+ * @param pLst The list of signatures to write.
+ * @param pDesc The signature type descriptor.
+ * @param hVfsFileOut The file to write the database to.
+ * @param pcbThisWritten Where to store the number of bytes written for the given signature list.
+ */
+static int rtEfiSigDbWriteListSingle(PRTLISTANCHOR pLst, PCRTEFISIGDBDESC pDesc, RTVFSFILE hVfsFileOut, size_t *pcbThisWritten)
+{
+ int rc = VINF_SUCCESS;
+ size_t cbWritten = 0;
+ PRTEFISIGNATURE pIt;
+
+ RTListForEach(pLst, pIt, RTEFISIGNATURE, NdLst)
+ {
+ EFI_SIGNATURE_LIST LstHdr;
+ EFI_SIGNATURE_DATA SigData;
+ LstHdr.GuidSigType = pDesc->GuidSignatureType;
+ LstHdr.cbSigLst = RT_H2LE_U32(sizeof(LstHdr) + sizeof(SigData) + pDesc->cbSigHdr + pIt->cbSignature);
+ LstHdr.cbSigHdr = RT_H2LE_U32(pDesc->cbSigHdr);
+ LstHdr.cbSig = RT_H2LE_U32(pIt->cbSignature + sizeof(SigData));
+ RTEfiGuidFromUuid(&SigData.GuidOwner, &pIt->UuidOwner);
+
+ RTSGSEG aSegs[3];
+ RTSGBUF SgBuf;
+
+ Assert(!pDesc->cbSigHdr);
+ aSegs[0].pvSeg = &LstHdr;
+ aSegs[0].cbSeg = sizeof(LstHdr);
+ aSegs[1].pvSeg = &SigData;
+ aSegs[1].cbSeg = sizeof(SigData);
+ aSegs[2].pvSeg = &pIt->abSignature[0];
+ aSegs[2].cbSeg = pIt->cbSignature;
+ RTSgBufInit(&SgBuf, &aSegs[0], RT_ELEMENTS(aSegs));
+ rc = RTVfsFileSgWrite(hVfsFileOut, -1, &SgBuf, true /*fBlocking*/, NULL /*pcbWritten*/);
+ if (RT_FAILURE(rc))
+ break;
+
+ cbWritten += sizeof(LstHdr) + sizeof(SigData) + pDesc->cbSigHdr + pIt->cbSignature;
+ }
+
+ if (RT_SUCCESS(rc))
+ *pcbThisWritten = cbWritten;
+
+ return rc;
+}
+
+
+/**
+ * Writes the given signature list to the database in the given file.
+ *
+ * @returns IPRT status code.
+ * @param pLst The list of signatures to write.
+ * @param pDesc The signature type descriptor.
+ * @param hVfsFileOut The file to write the database to.
+ * @param pcbThisWritten Where to store the number of bytes written for the given signature list.
+ */
+static int rtEfiSigDbWriteList(PRTLISTANCHOR pLst, PCRTEFISIGDBDESC pDesc, RTVFSFILE hVfsFileOut, size_t *pcbThisWritten)
+{
+ /*
+ * For signature lists where each signature can have a different size (X.509 for example)
+ * writing a new list for each signature is required which is done by a dedicated method.
+ */
+ if (!pDesc->cbSig)
+ return rtEfiSigDbWriteListSingle(pLst, pDesc, hVfsFileOut, pcbThisWritten);
+
+
+ /* Count the number of signatures first. */
+ uint32_t cSigs = 0;
+ PRTEFISIGNATURE pIt;
+
+ RTListForEach(pLst, pIt, RTEFISIGNATURE, NdLst)
+ {
+ cSigs++;
+ }
+
+ EFI_SIGNATURE_LIST LstHdr;
+ LstHdr.GuidSigType = pDesc->GuidSignatureType;
+ LstHdr.cbSigLst = RT_H2LE_U32(sizeof(LstHdr) + pDesc->cbSigHdr + cSigs * pDesc->cbSig);
+ LstHdr.cbSigHdr = RT_H2LE_U32(pDesc->cbSigHdr);
+ LstHdr.cbSig = RT_H2LE_U32(pDesc->cbSig);
+
+ int rc = RTVfsFileWrite(hVfsFileOut, &LstHdr, sizeof(LstHdr), NULL /*pcbWritten*/);
+ if (RT_SUCCESS(rc))
+ {
+ RTListForEach(pLst, pIt, RTEFISIGNATURE, NdLst)
+ {
+ RTSGSEG aSegs[2];
+ RTSGBUF SgBuf;
+ EFI_SIGNATURE_DATA SigData;
+ RTEfiGuidFromUuid(&SigData.GuidOwner, &pIt->UuidOwner);
+
+ Assert(pDesc->cbSig == pIt->cbSignature);
+ aSegs[0].pvSeg = &SigData;
+ aSegs[0].cbSeg = sizeof(SigData);
+ aSegs[1].pvSeg = &pIt->abSignature[0];
+ aSegs[1].cbSeg = pIt->cbSignature;
+ RTSgBufInit(&SgBuf, &aSegs[0], RT_ELEMENTS(aSegs));
+ rc = RTVfsFileSgWrite(hVfsFileOut, -1, &SgBuf, true /*fBlocking*/, NULL /*pcbWritten*/);
+ if (RT_FAILURE(rc))
+ break;
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ *pcbThisWritten = sizeof(LstHdr) + pDesc->cbSigHdr + cSigs * pDesc->cbSig;
+
+ return rc;
+}
+
+
+/**
+ * Allocate a new signature of the given size.
+ *
+ * @returns Pointer to the new signature or NULL if out of memory.
+ * @param pUuidOwner The UUID of the signature owner.
+ * @param cbSig Size of the signature data in bytes.
+ */
+static PRTEFISIGNATURE rtEfiSigDbAllocSignature(PCRTUUID pUuidOwner, uint32_t cbSig)
+{
+ PRTEFISIGNATURE pSig = (PRTEFISIGNATURE)RTMemAllocZ(RT_UOFFSETOF_DYN(RTEFISIGNATURE, abSignature[cbSig]));
+ if (pSig)
+ {
+ pSig->UuidOwner = *pUuidOwner;
+ pSig->cbSignature = cbSig;
+ }
+
+ return pSig;
+}
+
+
+RTDECL(int) RTEfiSigDbCreate(PRTEFISIGDB phEfiSigDb)
+{
+ AssertPtrReturn(phEfiSigDb, VERR_INVALID_POINTER);
+
+ PRTEFISIGDBINT pThis = (PRTEFISIGDBINT)RTMemAllocZ(sizeof(*pThis));
+ if (RT_LIKELY(pThis))
+ {
+ for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aLstSigTypes); i++)
+ RTListInit(&pThis->aLstSigTypes[i]);
+ *phEfiSigDb = pThis;
+ return VINF_SUCCESS;
+ }
+
+ return VERR_NO_MEMORY;
+}
+
+
+RTDECL(int) RTEfiSigDbDestroy(RTEFISIGDB hEfiSigDb)
+{
+ PRTEFISIGDBINT pThis = hEfiSigDb;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+
+ for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aLstSigTypes); i++)
+ {
+ PRTEFISIGNATURE pIt, pItNext;
+
+ RTListForEachSafe(&pThis->aLstSigTypes[i], pIt, pItNext, RTEFISIGNATURE, NdLst)
+ {
+ RTListNodeRemove(&pIt->NdLst);
+ RTMemFree(pIt);
+ }
+ }
+
+ RTMemFree(pThis);
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTEfiSigDbAddFromExistingDb(RTEFISIGDB hEfiSigDb, RTVFSFILE hVfsFileIn)
+{
+ PRTEFISIGDBINT pThis = hEfiSigDb;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+
+ uint64_t cbFile;
+ int rc = RTVfsFileQuerySize(hVfsFileIn, &cbFile);
+ if ( RT_SUCCESS(rc)
+ && cbFile)
+ {
+ do
+ {
+ uint64_t cbConsumed = 0;
+ rc = rtEfiSigDbLoadSigList(pThis, hVfsFileIn, &cbConsumed);
+ cbFile -= cbConsumed;
+ } while ( RT_SUCCESS(rc)
+ && cbFile);
+ }
+
+ return rc;
+}
+
+
+RTDECL(int) RTEfiSigDbAddSignatureFromFile(RTEFISIGDB hEfiSigDb, RTEFISIGTYPE enmSigType, PCRTUUID pUuidOwner, RTVFSFILE hVfsFileIn)
+{
+ PRTEFISIGDBINT pThis = hEfiSigDb;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(enmSigType >= RTEFISIGTYPE_FIRST_VALID && enmSigType < RTEFISIGTYPE_FIRST_INVALID, VERR_INVALID_PARAMETER);
+ AssertPtrReturn(pUuidOwner, VERR_INVALID_POINTER);
+
+ PCRTEFISIGDBDESC pDesc = &g_aGuid2SigTypeMapping[enmSigType];
+ uint64_t cbSig = 0;
+ int rc = RTVfsFileQuerySize(hVfsFileIn, &cbSig);
+ if (RT_SUCCESS(rc))
+ {
+ if ( ( !pDesc->cbSig
+ || pDesc->cbSig - sizeof(EFI_SIGNATURE_DATA) == cbSig)
+ && cbSig < UINT32_MAX)
+ {
+ PRTEFISIGNATURE pSig = rtEfiSigDbAllocSignature(pUuidOwner, (uint32_t)cbSig);
+ if (pSig)
+ {
+ rc = RTVfsFileRead(hVfsFileIn, &pSig->abSignature[0], (size_t)cbSig, NULL /*pcbRead*/);
+ if (RT_SUCCESS(rc))
+ RTListAppend(&pThis->aLstSigTypes[enmSigType], &pSig->NdLst);
+ else
+ RTMemFree(pSig);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ else
+ rc = VERR_INVALID_PARAMETER;
+ }
+
+ return rc;
+}
+
+
+RTDECL(int) RTEfiSigDbAddSignatureFromBuf(RTEFISIGDB hEfiSigDb, RTEFISIGTYPE enmSigType, PCRTUUID pUuidOwner,
+ const void *pvBuf, size_t cbBuf)
+{
+ PRTEFISIGDBINT pThis = hEfiSigDb;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(enmSigType >= RTEFISIGTYPE_FIRST_VALID && enmSigType < RTEFISIGTYPE_FIRST_INVALID, VERR_INVALID_PARAMETER);
+ AssertPtrReturn(pUuidOwner, VERR_INVALID_POINTER);
+ AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+ AssertReturn(cbBuf && cbBuf < UINT32_MAX, VERR_INVALID_PARAMETER);
+
+ int rc = VINF_SUCCESS;
+ PCRTEFISIGDBDESC pDesc = &g_aGuid2SigTypeMapping[enmSigType];
+ if ( !pDesc->cbSig
+ || pDesc->cbSig - sizeof(EFI_SIGNATURE_DATA) == cbBuf)
+ {
+ PRTEFISIGNATURE pSig = rtEfiSigDbAllocSignature(pUuidOwner, (uint32_t)cbBuf);
+ if (pSig)
+ {
+ memcpy(&pSig->abSignature[0], pvBuf, cbBuf);
+ RTListAppend(&pThis->aLstSigTypes[enmSigType], &pSig->NdLst);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ else
+ rc = VERR_INVALID_PARAMETER;
+
+ return rc;
+}
+
+
+RTDECL(int) RTEfiSigDbWriteToFile(RTEFISIGDB hEfiSigDb, RTVFSFILE hVfsFileOut)
+{
+ PRTEFISIGDBINT pThis = hEfiSigDb;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+
+ int rc = VINF_SUCCESS;
+ size_t cbSigDb = 0;
+ for (uint32_t i = RTEFISIGTYPE_FIRST_VALID; i < RT_ELEMENTS(pThis->aLstSigTypes) && RT_SUCCESS(rc); i++)
+ {
+ if (!RTListIsEmpty(&pThis->aLstSigTypes[i]))
+ {
+ size_t cbThisWritten = 0;
+ rc = rtEfiSigDbWriteList(&pThis->aLstSigTypes[i], &g_aGuid2SigTypeMapping[i], hVfsFileOut, &cbThisWritten);
+ if (RT_SUCCESS(rc))
+ cbSigDb += cbThisWritten;
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ rc = RTVfsFileSetSize(hVfsFileOut, cbSigDb, RTVFSFILE_SIZE_F_NORMAL);
+
+ return rc;
+}
+
+
+RTDECL(int) RTEfiSigDbEnum(RTEFISIGDB hEfiSigDb, PFNRTEFISIGDBENUMSIG pfnEnumSig, void *pvUser)
+{
+ PRTEFISIGDBINT pThis = hEfiSigDb;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+
+ for (uint32_t i = RTEFISIGTYPE_FIRST_VALID; i < RT_ELEMENTS(pThis->aLstSigTypes); i++)
+ {
+ PRTEFISIGNATURE pIt;
+
+ RTListForEach(&pThis->aLstSigTypes[i], pIt, RTEFISIGNATURE, NdLst)
+ {
+ int rc = pfnEnumSig(pThis, (RTEFISIGTYPE)i, &pIt->UuidOwner, &pIt->abSignature[0], pIt->cbSignature, pvUser);
+ if (rc != VINF_SUCCESS)
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(const char *) RTEfiSigDbTypeStringify(RTEFISIGTYPE enmSigType)
+{
+ AssertReturn(enmSigType < RTEFISIGTYPE_FIRST_INVALID, NULL);
+ return g_aGuid2SigTypeMapping[enmSigType].pszName;
+}
+
+
+RTDECL(PCEFI_GUID) RTEfiSigDbTypeGetGuid(RTEFISIGTYPE enmSigType)
+{
+ AssertReturn(enmSigType < RTEFISIGTYPE_FIRST_INVALID, NULL);
+ return &g_aGuid2SigTypeMapping[enmSigType].GuidSignatureType;
+}
+