VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/efi/efisignaturedb.cpp@ 106580

Last change on this file since 106580 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.6 KB
Line 
1/* $Id: efisignaturedb.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT - EFI signature database helpers.
4 */
5
6/*
7 * Copyright (C) 2021-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_DEFAULT
42#include <iprt/efi.h>
43
44#include <iprt/cdefs.h>
45#include <iprt/asm.h>
46#include <iprt/string.h>
47#include <iprt/list.h>
48#include <iprt/mem.h>
49#include <iprt/sg.h>
50#include <iprt/uuid.h>
51
52#include <iprt/formats/efi-signature.h>
53
54
55/*********************************************************************************************************************************
56* Defined Constants And Macros *
57*********************************************************************************************************************************/
58
59
60/*********************************************************************************************************************************
61* Structures and Typedefs *
62*********************************************************************************************************************************/
63
64/**
65 * EFI signature entry.
66 */
67typedef struct RTEFISIGNATURE
68{
69 /** List node. */
70 RTLISTNODE NdLst;
71 /** The signature owner. */
72 RTUUID UuidOwner;
73 /** Size of the signature data in bytes. */
74 uint32_t cbSignature;
75 /** The signature data (variable in size). */
76 RT_FLEXIBLE_ARRAY_EXTENSION
77 uint8_t abSignature[RT_FLEXIBLE_ARRAY];
78} RTEFISIGNATURE;
79/** Pointer to a EFI signature entry. */
80typedef RTEFISIGNATURE *PRTEFISIGNATURE;
81/** Pointer to a const EFI signature entry. */
82typedef const RTEFISIGNATURE *PCRTEFISIGNATURE;
83
84
85/**
86 * The EFI signature database instance data.
87 */
88typedef struct RTEFISIGDBINT
89{
90 /** List head of the various signature types. */
91 RTLISTANCHOR aLstSigTypes[RTEFISIGTYPE_FIRST_INVALID];
92} RTEFISIGDBINT;
93/** Pointer to the EFI signature database instance data. */
94typedef RTEFISIGDBINT *PRTEFISIGDBINT;
95
96
97/**
98 * Signature type descriptor.
99 */
100typedef struct RTEFISIGDBDESC
101{
102 /** The EFI GUID identifying the signature type. */
103 EFI_GUID GuidSignatureType;
104 /** The additional signature header for this signature type. */
105 uint32_t cbSigHdr;
106 /** Size of the signature data (including EFI_SIGNATURE_DATA),
107 * can be 0 size varies with each signature (X.509 for example). */
108 uint32_t cbSig;
109 /** The internal signature type enum. */
110 RTEFISIGTYPE enmSigType;
111 /** Human readable string of the signature type. */
112 const char *pszName;
113} RTEFISIGDBDESC;
114/** Pointer to a signature type descriptor. */
115typedef RTEFISIGDBDESC *PRTEFISIGDBDESC;
116/** Pointer to a const signature type descriptor. */
117typedef const RTEFISIGDBDESC *PCRTEFISIGDBDESC;
118
119
120/*********************************************************************************************************************************
121* Global Variables *
122*********************************************************************************************************************************/
123
124/**
125 * Mapping of EFI signature GUIDs to their IPRT signature type equivalent.
126 */
127static const RTEFISIGDBDESC g_aGuid2SigTypeMapping[] =
128{
129 { EFI_NULL_GUID, 0, 0, RTEFISIGTYPE_INVALID, "INVALID" },
130 { EFI_SIGNATURE_TYPE_GUID_SHA256, 0, EFI_SIGNATURE_TYPE_SZ_SHA256, RTEFISIGTYPE_SHA256, "SHA-256" },
131 { EFI_SIGNATURE_TYPE_GUID_RSA2048, 0, EFI_SIGNATURE_TYPE_SZ_RSA2048, RTEFISIGTYPE_RSA2048, "RSA-2048" },
132 { EFI_SIGNATURE_TYPE_GUID_RSA2048_SHA256, 0, EFI_SIGNATURE_TYPE_SZ_RSA2048_SHA256, RTEFISIGTYPE_RSA2048_SHA256, "RSA-2048/SHA-256" },
133 { EFI_SIGNATURE_TYPE_GUID_SHA1, 0, EFI_SIGNATURE_TYPE_SZ_SHA1, RTEFISIGTYPE_SHA1, "SHA-1" },
134 { EFI_SIGNATURE_TYPE_GUID_RSA2048_SHA1, 0, EFI_SIGNATURE_TYPE_SZ_RSA2048_SHA1, RTEFISIGTYPE_RSA2048_SHA1, "RSA-2048/SHA-1" },
135 { EFI_SIGNATURE_TYPE_GUID_X509, 0, 0, RTEFISIGTYPE_X509, "X.509" }
136};
137
138
139/*********************************************************************************************************************************
140* Internal Functions *
141*********************************************************************************************************************************/
142
143
144/**
145 * Returns the internal siganture type descriptor for the given EFI GUID.
146 *
147 * @returns Pointer to the descriptor if found or NULL if not.
148 * @param pGuid The EFI signature type GUID to look for.
149 */
150static PCRTEFISIGDBDESC rtEfiSigDbGetDescByGuid(PCEFI_GUID pGuid)
151{
152 for (uint32_t i = 0; i < RT_ELEMENTS(g_aGuid2SigTypeMapping); i++)
153 if (!RTEfiGuidCompare(&g_aGuid2SigTypeMapping[i].GuidSignatureType, pGuid))
154 return &g_aGuid2SigTypeMapping[i];
155
156 return NULL;
157}
158
159
160/**
161 * Validates the given signature list header.
162 *
163 * @returns Flag whether the list header is considered valid.
164 * @param pLstHdr The list header to validate.
165 * @param pDesc The descriptor for the signature type of the given list.
166 */
167static bool rtEfiSigDbSigHdrValidate(PCEFI_SIGNATURE_LIST pLstHdr, PCRTEFISIGDBDESC pDesc)
168{
169 uint32_t cbSigLst = RT_LE2H_U32(pLstHdr->cbSigLst);
170 uint32_t cbSigHdr = RT_LE2H_U32(pLstHdr->cbSigHdr);
171 uint32_t cbSig = RT_LE2H_U32(pLstHdr->cbSig);
172
173 if (cbSigHdr != pDesc->cbSigHdr)
174 return false;
175 if (cbSig < sizeof(EFI_SIGNATURE_DATA))
176 return false;
177 if ( pDesc->cbSig
178 && pLstHdr->cbSig != pDesc->cbSig)
179 return false;
180 if ( cbSigLst <= sizeof(*pLstHdr)
181 || cbSigLst <= cbSigHdr
182 || cbSigLst <= cbSig)
183 return false;
184 if ((cbSigLst - sizeof(*pLstHdr) - cbSigHdr) % cbSig)
185 return false;
186
187 return true;
188}
189
190
191/**
192 * Loads a single signature list into the given signature database from the given file.
193 *
194 * @returns IPRT status code.
195 * @param pThis The signature database instance.
196 * @param hVfsFileIn The file to load the signature list from.
197 * @param pcbConsumed Where to store the number of bytes consumed for this signature list on success.
198 */
199static int rtEfiSigDbLoadSigList(PRTEFISIGDBINT pThis, RTVFSFILE hVfsFileIn, uint64_t *pcbConsumed)
200{
201 EFI_SIGNATURE_LIST LstHdr;
202 int rc = RTVfsFileRead(hVfsFileIn, &LstHdr, sizeof(LstHdr), NULL /*pcbRead*/);
203 if (RT_SUCCESS(rc))
204 {
205 PCRTEFISIGDBDESC pDesc = rtEfiSigDbGetDescByGuid(&LstHdr.GuidSigType);
206 if (pDesc)
207 {
208 if (rtEfiSigDbSigHdrValidate(&LstHdr, pDesc))
209 {
210 RTLISTANCHOR LstTmp;
211 uint32_t cbSig = RT_LE2H_U32(LstHdr.cbSig);
212 uint32_t cbSigData = cbSig - sizeof(EFI_SIGNATURE_DATA);
213 uint32_t cSigs = (RT_LE2H_U32(LstHdr.cbSigLst) - RT_LE2H_U32(LstHdr.cbSigHdr)) / cbSig;
214
215 /** @todo Skip/parse signature header if we have to add a type which has this != 0. */
216 RTListInit(&LstTmp);
217 for (uint32_t i = 0; i < cSigs && RT_SUCCESS(rc); i++)
218 {
219 PRTEFISIGNATURE pSig = (PRTEFISIGNATURE)RTMemAllocZ(RT_UOFFSETOF_DYN(RTEFISIGNATURE, abSignature[cbSigData]));
220 if (pSig)
221 {
222 EFI_SIGNATURE_DATA SigData;
223 rc = RTVfsFileRead(hVfsFileIn, &SigData, sizeof(SigData), NULL /*pcbRead*/);
224 if (RT_SUCCESS(rc))
225 rc = RTVfsFileRead(hVfsFileIn, &pSig->abSignature[0], cbSigData, NULL /*pcbRead*/);
226 if (RT_SUCCESS(rc))
227 {
228 RTEfiGuidToUuid(&pSig->UuidOwner, &SigData.GuidOwner);
229 pSig->cbSignature = cbSigData;
230 RTListAppend(&LstTmp, &pSig->NdLst);
231 }
232 else
233 RTMemFree(pSig);
234 }
235 else
236 rc = VERR_NO_MEMORY;
237 }
238
239 if (RT_SUCCESS(rc))
240 {
241 /* Add the signatures to the list. */
242 RTListConcatenate(&pThis->aLstSigTypes[pDesc->enmSigType], &LstTmp);
243 *pcbConsumed = sizeof(LstHdr) + RT_LE2H_U32(LstHdr.cbSigHdr) + cSigs * cbSig;
244 }
245 else
246 {
247 /* Destroy the temporary list. */
248 PRTEFISIGNATURE pIt, pItNext;
249
250 RTListForEachSafe(&LstTmp, pIt, pItNext, RTEFISIGNATURE, NdLst)
251 {
252 RTListNodeRemove(&pIt->NdLst);
253 RTMemFree(pIt);
254 }
255 }
256 }
257 else
258 rc = VERR_NOT_SUPPORTED;
259 }
260 else
261 rc = VERR_NOT_SUPPORTED;
262 }
263
264 return rc;
265}
266
267
268/**
269 * De-duplicate a signature database.
270 *
271 * @returns IPRT status code.
272 * @param pThis The signature database instance.
273 */
274static int rtEfiSigDbDeduplicate(PRTEFISIGDBINT pThis)
275{
276 /** @todo This currently deduplicates list nodes as a whole, not looking into signature lists.
277 * Good enough for the X.509 certificates which matter most to eliminate multiple enrollments. */
278 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aLstSigTypes); i++)
279 {
280 PRTEFISIGNATURE pIt, pItNext;
281 RTListForEachSafe(&pThis->aLstSigTypes[i], pIt, pItNext, RTEFISIGNATURE, NdLst)
282 {
283 PRTEFISIGNATURE pIt2;
284 RTListForEach(&pThis->aLstSigTypes[i], pIt2, RTEFISIGNATURE, NdLst)
285 {
286 /* Compare up to element before pIt. */
287 if (pIt == pIt2)
288 break;
289 if ( pIt->cbSignature == pIt2->cbSignature
290 && !RTUuidCompare(&pIt->UuidOwner, &pIt2->UuidOwner)
291 && !memcmp(&pIt->abSignature[0], &pIt2->abSignature[0], pIt->cbSignature))
292 {
293 RTListNodeRemove(&pIt->NdLst);
294 RTMemFree(pIt);
295 break;
296 }
297 }
298 }
299 }
300
301 return VINF_SUCCESS;
302}
303
304
305/**
306 * Variant for writing a list of signatures where each signature gets its own signature list header
307 * (for types where each signature can differ in size like X.509).
308 *
309 * @returns IPRT status code.
310 * @param pLst The list of signatures to write.
311 * @param pDesc The signature type descriptor.
312 * @param hVfsFileOut The file to write the database to.
313 * @param pcbThisWritten Where to store the number of bytes written for the given signature list.
314 */
315static int rtEfiSigDbWriteListSingle(PRTLISTANCHOR pLst, PCRTEFISIGDBDESC pDesc, RTVFSFILE hVfsFileOut, size_t *pcbThisWritten)
316{
317 int rc = VINF_SUCCESS;
318 size_t cbWritten = 0;
319 PRTEFISIGNATURE pIt;
320
321 RTListForEach(pLst, pIt, RTEFISIGNATURE, NdLst)
322 {
323 EFI_SIGNATURE_LIST LstHdr;
324 EFI_SIGNATURE_DATA SigData;
325 LstHdr.GuidSigType = pDesc->GuidSignatureType;
326 LstHdr.cbSigLst = RT_H2LE_U32(sizeof(LstHdr) + sizeof(SigData) + pDesc->cbSigHdr + pIt->cbSignature);
327 LstHdr.cbSigHdr = RT_H2LE_U32(pDesc->cbSigHdr);
328 LstHdr.cbSig = RT_H2LE_U32(pIt->cbSignature + sizeof(SigData));
329 RTEfiGuidFromUuid(&SigData.GuidOwner, &pIt->UuidOwner);
330
331 RTSGSEG aSegs[3];
332 RTSGBUF SgBuf;
333
334 Assert(!pDesc->cbSigHdr);
335 aSegs[0].pvSeg = &LstHdr;
336 aSegs[0].cbSeg = sizeof(LstHdr);
337 aSegs[1].pvSeg = &SigData;
338 aSegs[1].cbSeg = sizeof(SigData);
339 aSegs[2].pvSeg = &pIt->abSignature[0];
340 aSegs[2].cbSeg = pIt->cbSignature;
341 RTSgBufInit(&SgBuf, &aSegs[0], RT_ELEMENTS(aSegs));
342 rc = RTVfsFileSgWrite(hVfsFileOut, -1, &SgBuf, true /*fBlocking*/, NULL /*pcbWritten*/);
343 if (RT_FAILURE(rc))
344 break;
345
346 cbWritten += sizeof(LstHdr) + sizeof(SigData) + pDesc->cbSigHdr + pIt->cbSignature;
347 }
348
349 if (RT_SUCCESS(rc))
350 *pcbThisWritten = cbWritten;
351
352 return rc;
353}
354
355
356/**
357 * Writes the given signature list to the database in the given file.
358 *
359 * @returns IPRT status code.
360 * @param pLst The list of signatures to write.
361 * @param pDesc The signature type descriptor.
362 * @param hVfsFileOut The file to write the database to.
363 * @param pcbThisWritten Where to store the number of bytes written for the given signature list.
364 */
365static int rtEfiSigDbWriteList(PRTLISTANCHOR pLst, PCRTEFISIGDBDESC pDesc, RTVFSFILE hVfsFileOut, size_t *pcbThisWritten)
366{
367 /*
368 * For signature lists where each signature can have a different size (X.509 for example)
369 * writing a new list for each signature is required which is done by a dedicated method.
370 */
371 if (!pDesc->cbSig)
372 return rtEfiSigDbWriteListSingle(pLst, pDesc, hVfsFileOut, pcbThisWritten);
373
374
375 /* Count the number of signatures first. */
376 uint32_t cSigs = 0;
377 PRTEFISIGNATURE pIt;
378
379 RTListForEach(pLst, pIt, RTEFISIGNATURE, NdLst)
380 {
381 cSigs++;
382 }
383
384 EFI_SIGNATURE_LIST LstHdr;
385 LstHdr.GuidSigType = pDesc->GuidSignatureType;
386 LstHdr.cbSigLst = RT_H2LE_U32(sizeof(LstHdr) + pDesc->cbSigHdr + cSigs * pDesc->cbSig);
387 LstHdr.cbSigHdr = RT_H2LE_U32(pDesc->cbSigHdr);
388 LstHdr.cbSig = RT_H2LE_U32(pDesc->cbSig);
389
390 int rc = RTVfsFileWrite(hVfsFileOut, &LstHdr, sizeof(LstHdr), NULL /*pcbWritten*/);
391 if (RT_SUCCESS(rc))
392 {
393 RTListForEach(pLst, pIt, RTEFISIGNATURE, NdLst)
394 {
395 RTSGSEG aSegs[2];
396 RTSGBUF SgBuf;
397 EFI_SIGNATURE_DATA SigData;
398 RTEfiGuidFromUuid(&SigData.GuidOwner, &pIt->UuidOwner);
399
400 Assert(pDesc->cbSig == pIt->cbSignature);
401 aSegs[0].pvSeg = &SigData;
402 aSegs[0].cbSeg = sizeof(SigData);
403 aSegs[1].pvSeg = &pIt->abSignature[0];
404 aSegs[1].cbSeg = pIt->cbSignature;
405 RTSgBufInit(&SgBuf, &aSegs[0], RT_ELEMENTS(aSegs));
406 rc = RTVfsFileSgWrite(hVfsFileOut, -1, &SgBuf, true /*fBlocking*/, NULL /*pcbWritten*/);
407 if (RT_FAILURE(rc))
408 break;
409 }
410 }
411
412 if (RT_SUCCESS(rc))
413 *pcbThisWritten = sizeof(LstHdr) + pDesc->cbSigHdr + cSigs * pDesc->cbSig;
414
415 return rc;
416}
417
418
419/**
420 * Allocate a new signature of the given size.
421 *
422 * @returns Pointer to the new signature or NULL if out of memory.
423 * @param pUuidOwner The UUID of the signature owner.
424 * @param cbSig Size of the signature data in bytes.
425 */
426static PRTEFISIGNATURE rtEfiSigDbAllocSignature(PCRTUUID pUuidOwner, uint32_t cbSig)
427{
428 PRTEFISIGNATURE pSig = (PRTEFISIGNATURE)RTMemAllocZ(RT_UOFFSETOF_DYN(RTEFISIGNATURE, abSignature[cbSig]));
429 if (pSig)
430 {
431 pSig->UuidOwner = *pUuidOwner;
432 pSig->cbSignature = cbSig;
433 }
434
435 return pSig;
436}
437
438
439RTDECL(int) RTEfiSigDbCreate(PRTEFISIGDB phEfiSigDb)
440{
441 AssertPtrReturn(phEfiSigDb, VERR_INVALID_POINTER);
442
443 PRTEFISIGDBINT pThis = (PRTEFISIGDBINT)RTMemAllocZ(sizeof(*pThis));
444 if (RT_LIKELY(pThis))
445 {
446 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aLstSigTypes); i++)
447 RTListInit(&pThis->aLstSigTypes[i]);
448 *phEfiSigDb = pThis;
449 return VINF_SUCCESS;
450 }
451
452 return VERR_NO_MEMORY;
453}
454
455
456RTDECL(int) RTEfiSigDbDestroy(RTEFISIGDB hEfiSigDb)
457{
458 PRTEFISIGDBINT pThis = hEfiSigDb;
459 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
460
461 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aLstSigTypes); i++)
462 {
463 PRTEFISIGNATURE pIt, pItNext;
464
465 RTListForEachSafe(&pThis->aLstSigTypes[i], pIt, pItNext, RTEFISIGNATURE, NdLst)
466 {
467 RTListNodeRemove(&pIt->NdLst);
468 RTMemFree(pIt);
469 }
470 }
471
472 RTMemFree(pThis);
473 return VINF_SUCCESS;
474}
475
476
477RTDECL(int) RTEfiSigDbAddFromExistingDb(RTEFISIGDB hEfiSigDb, RTVFSFILE hVfsFileIn)
478{
479 PRTEFISIGDBINT pThis = hEfiSigDb;
480 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
481
482 uint64_t cbFile;
483 int rc = RTVfsFileQuerySize(hVfsFileIn, &cbFile);
484 if ( RT_SUCCESS(rc)
485 && cbFile)
486 {
487 do
488 {
489 uint64_t cbConsumed = 0;
490 rc = rtEfiSigDbLoadSigList(pThis, hVfsFileIn, &cbConsumed);
491 cbFile -= cbConsumed;
492 } while ( RT_SUCCESS(rc)
493 && cbFile);
494 }
495
496 int rc2 = rtEfiSigDbDeduplicate(pThis);
497 if (RT_SUCCESS(rc))
498 rc = rc2;
499
500 return rc;
501}
502
503
504RTDECL(int) RTEfiSigDbAddSignatureFromFile(RTEFISIGDB hEfiSigDb, RTEFISIGTYPE enmSigType, PCRTUUID pUuidOwner, RTVFSFILE hVfsFileIn)
505{
506 PRTEFISIGDBINT pThis = hEfiSigDb;
507 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
508 AssertReturn(enmSigType >= RTEFISIGTYPE_FIRST_VALID && enmSigType < RTEFISIGTYPE_FIRST_INVALID, VERR_INVALID_PARAMETER);
509 AssertPtrReturn(pUuidOwner, VERR_INVALID_POINTER);
510
511 PCRTEFISIGDBDESC pDesc = &g_aGuid2SigTypeMapping[enmSigType];
512 uint64_t cbSig = 0;
513 int rc = RTVfsFileQuerySize(hVfsFileIn, &cbSig);
514 if (RT_SUCCESS(rc))
515 {
516 if ( ( !pDesc->cbSig
517 || pDesc->cbSig - sizeof(EFI_SIGNATURE_DATA) == cbSig)
518 && cbSig < UINT32_MAX)
519 {
520 PRTEFISIGNATURE pSig = rtEfiSigDbAllocSignature(pUuidOwner, (uint32_t)cbSig);
521 if (pSig)
522 {
523 rc = RTVfsFileRead(hVfsFileIn, &pSig->abSignature[0], (size_t)cbSig, NULL /*pcbRead*/);
524 if (RT_SUCCESS(rc))
525 RTListAppend(&pThis->aLstSigTypes[enmSigType], &pSig->NdLst);
526 else
527 RTMemFree(pSig);
528 }
529 else
530 rc = VERR_NO_MEMORY;
531 }
532 else
533 rc = VERR_INVALID_PARAMETER;
534 }
535
536 int rc2 = rtEfiSigDbDeduplicate(pThis);
537 if (RT_SUCCESS(rc))
538 rc = rc2;
539
540 return rc;
541}
542
543
544RTDECL(int) RTEfiSigDbAddSignatureFromBuf(RTEFISIGDB hEfiSigDb, RTEFISIGTYPE enmSigType, PCRTUUID pUuidOwner,
545 const void *pvBuf, size_t cbBuf)
546{
547 PRTEFISIGDBINT pThis = hEfiSigDb;
548 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
549 AssertReturn(enmSigType >= RTEFISIGTYPE_FIRST_VALID && enmSigType < RTEFISIGTYPE_FIRST_INVALID, VERR_INVALID_PARAMETER);
550 AssertPtrReturn(pUuidOwner, VERR_INVALID_POINTER);
551 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
552 AssertReturn(cbBuf && cbBuf < UINT32_MAX, VERR_INVALID_PARAMETER);
553
554 int rc = VINF_SUCCESS;
555 PCRTEFISIGDBDESC pDesc = &g_aGuid2SigTypeMapping[enmSigType];
556 if ( !pDesc->cbSig
557 || pDesc->cbSig - sizeof(EFI_SIGNATURE_DATA) == cbBuf)
558 {
559 PRTEFISIGNATURE pSig = rtEfiSigDbAllocSignature(pUuidOwner, (uint32_t)cbBuf);
560 if (pSig)
561 {
562 memcpy(&pSig->abSignature[0], pvBuf, cbBuf);
563 RTListAppend(&pThis->aLstSigTypes[enmSigType], &pSig->NdLst);
564 }
565 else
566 rc = VERR_NO_MEMORY;
567 }
568 else
569 rc = VERR_INVALID_PARAMETER;
570
571 int rc2 = rtEfiSigDbDeduplicate(pThis);
572 if (RT_SUCCESS(rc))
573 rc = rc2;
574
575 return rc;
576}
577
578
579RTDECL(int) RTEfiSigDbWriteToFile(RTEFISIGDB hEfiSigDb, RTVFSFILE hVfsFileOut)
580{
581 PRTEFISIGDBINT pThis = hEfiSigDb;
582 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
583
584 int rc = VINF_SUCCESS;
585 size_t cbSigDb = 0;
586 for (uint32_t i = RTEFISIGTYPE_FIRST_VALID; i < RT_ELEMENTS(pThis->aLstSigTypes) && RT_SUCCESS(rc); i++)
587 {
588 if (!RTListIsEmpty(&pThis->aLstSigTypes[i]))
589 {
590 size_t cbThisWritten = 0;
591 rc = rtEfiSigDbWriteList(&pThis->aLstSigTypes[i], &g_aGuid2SigTypeMapping[i], hVfsFileOut, &cbThisWritten);
592 if (RT_SUCCESS(rc))
593 cbSigDb += cbThisWritten;
594 }
595 }
596
597 if (RT_SUCCESS(rc))
598 rc = RTVfsFileSetSize(hVfsFileOut, cbSigDb, RTVFSFILE_SIZE_F_NORMAL);
599
600 return rc;
601}
602
603
604RTDECL(int) RTEfiSigDbEnum(RTEFISIGDB hEfiSigDb, PFNRTEFISIGDBENUMSIG pfnEnumSig, void *pvUser)
605{
606 PRTEFISIGDBINT pThis = hEfiSigDb;
607 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
608
609 for (uint32_t i = RTEFISIGTYPE_FIRST_VALID; i < RT_ELEMENTS(pThis->aLstSigTypes); i++)
610 {
611 PRTEFISIGNATURE pIt;
612
613 RTListForEach(&pThis->aLstSigTypes[i], pIt, RTEFISIGNATURE, NdLst)
614 {
615 int rc = pfnEnumSig(pThis, (RTEFISIGTYPE)i, &pIt->UuidOwner, &pIt->abSignature[0], pIt->cbSignature, pvUser);
616 if (rc != VINF_SUCCESS)
617 return rc;
618 }
619 }
620
621 return VINF_SUCCESS;
622}
623
624
625RTDECL(const char *) RTEfiSigDbTypeStringify(RTEFISIGTYPE enmSigType)
626{
627 AssertReturn(enmSigType < RTEFISIGTYPE_FIRST_INVALID, NULL);
628 return g_aGuid2SigTypeMapping[enmSigType].pszName;
629}
630
631
632RTDECL(PCEFI_GUID) RTEfiSigDbTypeGetGuid(RTEFISIGTYPE enmSigType)
633{
634 AssertReturn(enmSigType < RTEFISIGTYPE_FIRST_INVALID, NULL);
635 return &g_aGuid2SigTypeMapping[enmSigType].GuidSignatureType;
636}
637
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette