VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/UefiVariableStoreImpl.cpp@ 91458

Last change on this file since 91458 was 91458, checked in by vboxsync, 3 years ago

Main,FE/VBoxManage: Implement functionality to list and query UEFI variables, bugref:9580 [doxygen fix]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.6 KB
Line 
1/* $Id: UefiVariableStoreImpl.cpp 91458 2021-09-29 14:17:49Z vboxsync $ */
2/** @file
3 * VirtualBox COM NVRAM store class implementation
4 */
5
6/*
7 * Copyright (C) 2021 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN_UEFIVARIABLESTORE
19#include "LoggingNew.h"
20
21#include "UefiVariableStoreImpl.h"
22#include "NvramStoreImpl.h"
23#include "MachineImpl.h"
24
25#include "AutoStateDep.h"
26#include "AutoCaller.h"
27
28#include "TrustAnchorsAndCerts.h"
29
30#include <VBox/com/array.h>
31
32#include <iprt/cpp/utils.h>
33#include <iprt/efi.h>
34#include <iprt/file.h>
35#include <iprt/vfs.h>
36
37#include <iprt/formats/efi-varstore.h>
38#include <iprt/formats/efi-signature.h>
39
40// defines
41////////////////////////////////////////////////////////////////////////////////
42
43// globals
44////////////////////////////////////////////////////////////////////////////////
45
46/////////////////////////////////////////////////////////////////////////////
47// UefiVariableStore::Data structure
48/////////////////////////////////////////////////////////////////////////////
49
50struct UefiVariableStore::Data
51{
52 Data()
53 : pParent(NULL),
54 pMachine(NULL),
55 hVfsUefiVarStore(NIL_RTVFS)
56 { }
57
58 /** The NVRAM store owning this UEFI variable store intstance. */
59 NvramStore * const pParent;
60 /** The machine this UEFI variable store belongs to. */
61 Machine * const pMachine;
62 /** VFS handle to the UEFI variable store. */
63 RTVFS hVfsUefiVarStore;
64};
65
66// constructor / destructor
67////////////////////////////////////////////////////////////////////////////////
68
69DEFINE_EMPTY_CTOR_DTOR(UefiVariableStore)
70
71HRESULT UefiVariableStore::FinalConstruct()
72{
73 return BaseFinalConstruct();
74}
75
76void UefiVariableStore::FinalRelease()
77{
78 uninit();
79 BaseFinalRelease();
80}
81
82// public initializer/uninitializer for internal purposes only
83/////////////////////////////////////////////////////////////////////////////
84
85/**
86 * Initializes the UEFI variable store object.
87 *
88 * @returns COM result indicator.
89 * @param aParent The NVRAM store owning the UEFI NVRAM content.
90 * @param pMachine
91 * @param hVfsUefiVarStore The UEFI variable store VFS handle.
92 */
93HRESULT UefiVariableStore::init(NvramStore *aParent, Machine *pMachine, RTVFS hVfsUefiVarStore)
94{
95 LogFlowThisFuncEnter();
96 LogFlowThisFunc(("aParent: %p\n", aParent));
97
98 ComAssertRet(aParent, E_INVALIDARG);
99
100 /* Enclose the state transition NotReady->InInit->Ready */
101 AutoInitSpan autoInitSpan(this);
102 AssertReturn(autoInitSpan.isOk(), E_FAIL);
103
104 m = new Data();
105
106 /* share the parent weakly */
107 unconst(m->pParent) = aParent;
108 unconst(m->pMachine) = pMachine;
109 m->hVfsUefiVarStore = hVfsUefiVarStore;
110
111 autoInitSpan.setSucceeded();
112
113 LogFlowThisFuncLeave();
114 return S_OK;
115}
116
117
118/**
119 * Uninitializes the instance and sets the ready flag to FALSE.
120 * Called either from FinalRelease() or by the parent when it gets destroyed.
121 */
122void UefiVariableStore::uninit()
123{
124 LogFlowThisFuncEnter();
125
126 /* Enclose the state transition Ready->InUninit->NotReady */
127 AutoUninitSpan autoUninitSpan(this);
128 if (autoUninitSpan.uninitDone())
129 return;
130
131 RTVfsRelease(m->hVfsUefiVarStore);
132
133 unconst(m->pParent) = NULL;
134 unconst(m->pMachine) = NULL;
135
136 delete m;
137 m = NULL;
138
139 LogFlowThisFuncLeave();
140}
141
142
143HRESULT UefiVariableStore::getSecureBootEnabled(BOOL *pfEnabled)
144{
145 /* the machine needs to be mutable */
146 AutoMutableStateDependency adep(m->pMachine);
147 if (FAILED(adep.rc())) return adep.rc();
148
149 AutoReadLock rlock(this COMMA_LOCKVAL_SRC_POS);
150
151 HRESULT hrc = S_OK;
152 uint64_t cbVar = 0;
153 int vrc = i_uefiVarStoreQueryVarSz("PK", &cbVar);
154 if (RT_SUCCESS(vrc))
155 {
156 *pfEnabled = TRUE;
157
158 /* Check the SecureBootEnable variable for the override. */
159 vrc = i_uefiVarStoreQueryVarSz("SecureBootEnable", &cbVar);
160 if (RT_SUCCESS(vrc))
161 {
162 if (cbVar == sizeof(uint8_t))
163 {
164 uint8_t bVar = 0;
165 hrc = i_uefiVarStoreQueryVar("SecureBootEnable", &bVar, sizeof(bVar));
166 if (SUCCEEDED(hrc))
167 *pfEnabled = bVar == 0x0 ? FALSE : TRUE;
168 }
169 else
170 hrc = setError(E_FAIL, tr("The 'SecureBootEnable' variable size is bogus (expected 1, got %llu)"), cbVar);
171 }
172 else if (vrc != VERR_FILE_NOT_FOUND)
173 hrc = setError(E_FAIL, tr("Failed to query the 'SecureBootEnable' variable size: %Rrc"), vrc);
174 }
175 else if (vrc == VERR_FILE_NOT_FOUND) /* No platform key means no secure boot. */
176 *pfEnabled = FALSE;
177 else
178 hrc = setError(E_FAIL, tr("Failed to query the platform key variable size: %Rrc"), vrc);
179
180 return hrc;
181}
182
183
184HRESULT UefiVariableStore::setSecureBootEnabled(BOOL fEnabled)
185{
186 /* the machine needs to be mutable */
187 AutoMutableStateDependency adep(m->pMachine);
188 if (FAILED(adep.rc())) return adep.rc();
189
190 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
191
192 EFI_GUID GuidSecureBootEnable = EFI_SECURE_BOOT_ENABLE_DISABLE_GUID;
193 uint64_t cbVar = 0;
194 int vrc = i_uefiVarStoreQueryVarSz("PK", &cbVar);
195 if (RT_SUCCESS(vrc))
196 {
197 uint8_t bVar = fEnabled ? 0x1 : 0x0;
198 return i_uefiVarStoreSetVar(&GuidSecureBootEnable, "SecureBootEnable",
199 EFI_VAR_HEADER_ATTR_NON_VOLATILE
200 | EFI_VAR_HEADER_ATTR_BOOTSERVICE_ACCESS
201 | EFI_VAR_HEADER_ATTR_RUNTIME_ACCESS,
202 &bVar, sizeof(bVar));
203 }
204 else if (vrc == VERR_FILE_NOT_FOUND) /* No platform key means no secure boot support. */
205 return setError(VBOX_E_OBJECT_NOT_FOUND, tr("Secure boot is not available because the platform key (PK) is not enrolled"));
206
207 return setError(E_FAIL, tr("Failed to query the platform key variable size: %Rrc"), vrc);
208}
209
210
211HRESULT UefiVariableStore::addVariable(const com::Utf8Str &aName, const com::Guid &aOwnerUuid,
212 const std::vector<UefiVariableAttributes_T> &aAttributes,
213 const std::vector<BYTE> &aData)
214{
215 /* the machine needs to be mutable */
216 AutoMutableStateDependency adep(m->pMachine);
217 if (FAILED(adep.rc())) return adep.rc();
218
219 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
220
221 uint32_t fAttr = i_uefiVarAttrToMask(aAttributes);
222 EFI_GUID OwnerGuid;
223 RTEfiGuidFromUuid(&OwnerGuid, aOwnerUuid.raw());
224 return i_uefiVarStoreSetVar(&OwnerGuid, aName.c_str(), fAttr, &aData.front(), aData.size());
225}
226
227
228HRESULT UefiVariableStore::deleteVariable(const com::Utf8Str &aName, const com::Guid &aOwnerUuid)
229{
230 RT_NOREF(aName, aOwnerUuid);
231 return E_NOTIMPL;
232}
233
234
235HRESULT UefiVariableStore::changeVariable(const com::Utf8Str &aName, const std::vector<BYTE> &aData)
236{
237 RT_NOREF(aName, aData);
238 return E_NOTIMPL;
239}
240
241
242HRESULT UefiVariableStore::queryVariableByName(const com::Utf8Str &aName, com::Guid &aOwnerUuid,
243 std::vector<UefiVariableAttributes_T> &aAttributes,
244 std::vector<BYTE> &aData)
245{
246 RT_NOREF(aName, aOwnerUuid, aAttributes, aData);
247
248 HRESULT hrc = S_OK;
249 uint32_t fAttr;
250 int vrc = i_uefiVarStoreQueryVarAttr(aName.c_str(), &fAttr);
251 if (RT_SUCCESS(vrc))
252 {
253 RTUUID OwnerUuid;
254 vrc = i_uefiVarStoreQueryVarOwnerUuid(aName.c_str(), &OwnerUuid);
255 if (RT_SUCCESS(vrc))
256 {
257 uint64_t cbVar = 0;
258 vrc = i_uefiVarStoreQueryVarSz(aName.c_str(), &cbVar);
259 if (RT_SUCCESS(vrc))
260 {
261 aData.resize(cbVar);
262 hrc = i_uefiVarStoreQueryVar(aName.c_str(), &aData.front(), aData.size());
263 if (SUCCEEDED(hrc))
264 {
265 aOwnerUuid = com::Guid(OwnerUuid);
266 i_uefiAttrMaskToVec(fAttr, aAttributes);
267 }
268 }
269 else
270 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to query the size of variable '%s': %Rrc"), aName.c_str(), vrc);
271 }
272 else
273 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to query the owner UUID of variable '%s': %Rrc"), aName.c_str(), vrc);
274 }
275 else
276 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to query the attributes of variable '%s': %Rrc"), aName.c_str(), vrc);
277
278 return hrc;
279}
280
281
282HRESULT UefiVariableStore::queryVariables(std::vector<com::Utf8Str> &aNames,
283 std::vector<com::Guid> &aOwnerUuids)
284{
285 /* the machine needs to be mutable */
286 AutoMutableStateDependency adep(m->pMachine);
287 if (FAILED(adep.rc())) return adep.rc();
288
289 AutoReadLock rlock(this COMMA_LOCKVAL_SRC_POS);
290
291 RTVFSDIR hVfsDir = NIL_RTVFSDIR;
292 int vrc = RTVfsDirOpen(m->hVfsUefiVarStore, "by-name", 0 /*fFlags*/, &hVfsDir);
293 if (RT_SUCCESS(vrc))
294 {
295 RTDIRENTRYEX DirEntry;
296
297 vrc = RTVfsDirReadEx(hVfsDir, &DirEntry, NULL, RTFSOBJATTRADD_NOTHING);
298 for (;;)
299 {
300 RTUUID OwnerUuid;
301 vrc = i_uefiVarStoreQueryVarOwnerUuid(DirEntry.szName, &OwnerUuid);
302 if (RT_FAILURE(vrc))
303 break;
304
305 aNames.push_back(Utf8Str(DirEntry.szName));
306 aOwnerUuids.push_back(com::Guid(OwnerUuid));
307
308 vrc = RTVfsDirReadEx(hVfsDir, &DirEntry, NULL, RTFSOBJATTRADD_NOTHING);
309 if (RT_FAILURE(vrc))
310 break;
311 }
312
313 if (vrc == VERR_NO_MORE_FILES)
314 vrc = VINF_SUCCESS;
315
316 RTVfsDirRelease(hVfsDir);
317 }
318
319 if (RT_FAILURE(vrc))
320 return setError(VBOX_E_IPRT_ERROR, tr("Failed to query the variables: %Rrc"), vrc);
321
322 return S_OK;
323}
324
325
326HRESULT UefiVariableStore::enrollOraclePlatformKey(void)
327{
328 return E_NOTIMPL;
329}
330
331
332HRESULT UefiVariableStore::enrollPlatformKey(const std::vector<BYTE> &aData, const com::Guid &aOwnerUuid)
333{
334 /* the machine needs to be mutable */
335 AutoMutableStateDependency adep(m->pMachine);
336 if (FAILED(adep.rc())) return adep.rc();
337
338 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
339
340 EFI_GUID GuidGlobalVar = EFI_GLOBAL_VARIABLE_GUID;
341 return i_uefiVarStoreAddSignatureToDbVec(&GuidGlobalVar, "PK", aData, aOwnerUuid, SignatureType_X509);
342}
343
344
345HRESULT UefiVariableStore::addKek(const std::vector<BYTE> &aData, const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType)
346{
347 /* the machine needs to be mutable */
348 AutoMutableStateDependency adep(m->pMachine);
349 if (FAILED(adep.rc())) return adep.rc();
350
351 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
352
353 EFI_GUID GuidGlobalVar = EFI_GLOBAL_VARIABLE_GUID;
354 return i_uefiVarStoreAddSignatureToDbVec(&GuidGlobalVar, "KEK", aData, aOwnerUuid, enmSignatureType);
355}
356
357
358HRESULT UefiVariableStore::addSignatureToDb(const std::vector<BYTE> &aData, const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType)
359{
360 /* the machine needs to be mutable */
361 AutoMutableStateDependency adep(m->pMachine);
362 if (FAILED(adep.rc())) return adep.rc();
363
364 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
365
366 EFI_GUID GuidSecurityDb = EFI_GLOBAL_VARIABLE_GUID;
367 return i_uefiVarStoreAddSignatureToDbVec(&GuidSecurityDb, "db", aData, aOwnerUuid, enmSignatureType);
368}
369
370
371HRESULT UefiVariableStore::addSignatureToDbx(const std::vector<BYTE> &aData, const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType)
372{
373 /* the machine needs to be mutable */
374 AutoMutableStateDependency adep(m->pMachine);
375 if (FAILED(adep.rc())) return adep.rc();
376
377 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
378
379 EFI_GUID GuidSecurityDb = EFI_IMAGE_SECURITY_DATABASE_GUID;
380 return i_uefiVarStoreAddSignatureToDbVec(&GuidSecurityDb, "dbx", aData, aOwnerUuid, enmSignatureType);
381}
382
383
384HRESULT UefiVariableStore::enrollDefaultMsSignatures(void)
385{
386 AutoMutableStateDependency adep(m->pMachine);
387 if (FAILED(adep.rc())) return adep.rc();
388
389 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
390
391 EFI_GUID EfiGuidSecurityDb = EFI_IMAGE_SECURITY_DATABASE_GUID;
392 EFI_GUID EfiGuidGlobalVar = EFI_GLOBAL_VARIABLE_GUID;
393
394 /** @todo This conversion from EFI GUID -> IPRT UUID -> Com GUID is nuts... */
395 EFI_GUID EfiGuidMs = EFI_SIGNATURE_OWNER_GUID_MICROSOFT;
396 RTUUID UuidMs;
397 RTEfiGuidToUuid(&UuidMs, &EfiGuidMs);
398
399 const com::Guid GuidMs(UuidMs);
400
401 HRESULT hrc = i_uefiVarStoreAddSignatureToDb(&EfiGuidGlobalVar, "KEK", g_abUefiMicrosoftKek, g_cbUefiMicrosoftKek,
402 GuidMs, SignatureType_X509);
403 if (SUCCEEDED(hrc))
404 {
405 hrc = i_uefiVarStoreAddSignatureToDb(&EfiGuidSecurityDb, "db", g_abUefiMicrosoftCa, g_cbUefiMicrosoftCa,
406 GuidMs, SignatureType_X509);
407 if (SUCCEEDED(hrc))
408 hrc = i_uefiVarStoreAddSignatureToDb(&EfiGuidSecurityDb, "db", g_abUefiMicrosoftProPca, g_cbUefiMicrosoftProPca,
409 GuidMs, SignatureType_X509);
410 }
411
412 return hrc;
413}
414
415
416/**
417 * Sets the given attributes for the given EFI variable store variable.
418 *
419 * @returns IPRT status code.
420 * @param pszVar The variable to set the attributes for.
421 * @param fAttr The attributes to set, see EFI_VAR_HEADER_ATTR_XXX.
422 */
423int UefiVariableStore::i_uefiVarStoreSetVarAttr(const char *pszVar, uint32_t fAttr)
424{
425 char szVarPath[_1K];
426 ssize_t cch = RTStrPrintf2(szVarPath, sizeof(szVarPath), "/raw/%s/attr", pszVar);
427 Assert(cch > 0); RT_NOREF(cch);
428
429 RTVFSFILE hVfsFileAttr = NIL_RTVFSFILE;
430 int vrc = RTVfsFileOpen(m->hVfsUefiVarStore, szVarPath,
431 RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
432 &hVfsFileAttr);
433 if (RT_SUCCESS(vrc))
434 {
435 uint32_t fAttrLe = RT_H2LE_U32(fAttr);
436 vrc = RTVfsFileWrite(hVfsFileAttr, &fAttrLe, sizeof(fAttrLe), NULL /*pcbWritten*/);
437 RTVfsFileRelease(hVfsFileAttr);
438 }
439
440 return vrc;
441}
442
443
444/**
445 * Queries the attributes for the given EFI variable store variable.
446 *
447 * @returns IPRT status code.
448 * @param pszVar The variable to query the attributes for.
449 * @param pfAttr Where to store the attributes on success.
450 */
451int UefiVariableStore::i_uefiVarStoreQueryVarAttr(const char *pszVar, uint32_t *pfAttr)
452{
453 char szVarPath[_1K];
454 ssize_t cch = RTStrPrintf2(szVarPath, sizeof(szVarPath), "/raw/%s/attr", pszVar);
455 Assert(cch > 0); RT_NOREF(cch);
456
457 RTVFSFILE hVfsFileAttr = NIL_RTVFSFILE;
458 int vrc = RTVfsFileOpen(m->hVfsUefiVarStore, szVarPath,
459 RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
460 &hVfsFileAttr);
461 if (RT_SUCCESS(vrc))
462 {
463 uint32_t fAttrLe = 0;
464 vrc = RTVfsFileRead(hVfsFileAttr, &fAttrLe, sizeof(fAttrLe), NULL /*pcbRead*/);
465 RTVfsFileRelease(hVfsFileAttr);
466 if (RT_SUCCESS(vrc))
467 *pfAttr = RT_LE2H_U32(fAttrLe);
468 }
469
470 return vrc;
471}
472
473
474/**
475 * Queries the data size for the given variable.
476 *
477 * @returns IPRT status code.
478 * @param pszVar The variable to query the size for.
479 * @param pcbVar Where to store the size of the variable data on success.
480 */
481int UefiVariableStore::i_uefiVarStoreQueryVarSz(const char *pszVar, uint64_t *pcbVar)
482{
483 char szVarPath[_1K];
484 ssize_t cch = RTStrPrintf2(szVarPath, sizeof(szVarPath), "/by-name/%s", pszVar);
485 Assert(cch > 0); RT_NOREF(cch);
486
487 RTVFSFILE hVfsFile = NIL_RTVFSFILE;
488 int vrc = RTVfsFileOpen(m->hVfsUefiVarStore, szVarPath,
489 RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
490 &hVfsFile);
491 if (RT_SUCCESS(vrc))
492 {
493 vrc = RTVfsFileQuerySize(hVfsFile, pcbVar);
494 RTVfsFileRelease(hVfsFile);
495 }
496 else if (vrc == VERR_PATH_NOT_FOUND)
497 vrc = VERR_FILE_NOT_FOUND;
498
499 return vrc;
500}
501
502
503/**
504 * Returns the owner UUID of the given variable.
505 *
506 * @returns IPRT status code.
507 * @param pszVar The variable to query the owner UUID for.
508 * @param pUuid Where to store the owner UUID on success.
509 */
510int UefiVariableStore::i_uefiVarStoreQueryVarOwnerUuid(const char *pszVar, PRTUUID pUuid)
511{
512 char szVarPath[_1K];
513 ssize_t cch = RTStrPrintf2(szVarPath, sizeof(szVarPath), "/raw/%s/uuid", pszVar);
514 Assert(cch > 0); RT_NOREF(cch);
515
516 RTVFSFILE hVfsFileAttr = NIL_RTVFSFILE;
517 int vrc = RTVfsFileOpen(m->hVfsUefiVarStore, szVarPath,
518 RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
519 &hVfsFileAttr);
520 if (RT_SUCCESS(vrc))
521 {
522 EFI_GUID OwnerGuid;
523 vrc = RTVfsFileRead(hVfsFileAttr, &OwnerGuid, sizeof(OwnerGuid), NULL /*pcbRead*/);
524 RTVfsFileRelease(hVfsFileAttr);
525 if (RT_SUCCESS(vrc))
526 RTEfiGuidToUuid(pUuid, &OwnerGuid);
527 }
528
529 return vrc;
530}
531
532
533/**
534 * Converts the given vector of variables attributes to a bitmask used internally.
535 *
536 * @returns Mask of UEFI variable attributes.
537 * @param vecAttributes Vector of variable atttributes.
538 */
539uint32_t UefiVariableStore::i_uefiVarAttrToMask(const std::vector<UefiVariableAttributes_T> &vecAttributes)
540{
541 uint32_t fAttr = 0;
542
543 for (size_t i = 0; i < vecAttributes.size(); i++)
544 fAttr |= (ULONG)vecAttributes[i];
545
546 return fAttr;
547}
548
549
550/**
551 * Converts the given aatribute mask to the attribute vector used externally.
552 *
553 * @returns nothing.
554 * @param fAttr The attribute mask.
555 * @param aAttributes The vector to store the attibutes in.
556 */
557void UefiVariableStore::i_uefiAttrMaskToVec(uint32_t fAttr, std::vector<UefiVariableAttributes_T> &aAttributes)
558{
559 if (fAttr & EFI_VAR_HEADER_ATTR_NON_VOLATILE)
560 aAttributes.push_back(UefiVariableAttributes_NonVolatile);
561 if (fAttr & EFI_VAR_HEADER_ATTR_BOOTSERVICE_ACCESS)
562 aAttributes.push_back(UefiVariableAttributes_BootServiceAccess);
563 if (fAttr & EFI_VAR_HEADER_ATTR_RUNTIME_ACCESS)
564 aAttributes.push_back(UefiVariableAttributes_RuntimeAccess);
565 if (fAttr & EFI_VAR_HEADER_ATTR_HW_ERROR_RECORD)
566 aAttributes.push_back(UefiVariableAttributes_HwErrorRecord);
567 if (fAttr & EFI_AUTH_VAR_HEADER_ATTR_AUTH_WRITE_ACCESS)
568 aAttributes.push_back(UefiVariableAttributes_AuthWriteAccess);
569 if (fAttr & EFI_AUTH_VAR_HEADER_ATTR_TIME_BASED_AUTH_WRITE_ACCESS)
570 aAttributes.push_back(UefiVariableAttributes_AuthTimeBasedWriteAccess);
571 if (fAttr & EFI_AUTH_VAR_HEADER_ATTR_APPEND_WRITE)
572 aAttributes.push_back(UefiVariableAttributes_AuthAppendWrite);
573}
574
575
576/**
577 * Adds the given variable to the variable store.
578 *
579 * @returns IPRT status code.
580 * @param pGuid The EFI GUID of the variable.
581 * @param pszVar The variable name.
582 * @param fAttr Attributes for the variable.
583 * @param phVfsFile Where to return the VFS file handle to the created variable on success.
584 */
585HRESULT UefiVariableStore::i_uefiVarStoreAddVar(PCEFI_GUID pGuid, const char *pszVar, uint32_t fAttr, PRTVFSFILE phVfsFile)
586{
587 RTUUID UuidVar;
588 RTEfiGuidToUuid(&UuidVar, pGuid);
589
590 char szVarPath[_1K];
591 ssize_t cch = RTStrPrintf2(szVarPath, sizeof(szVarPath), "/by-uuid/%RTuuid/%s", &UuidVar, pszVar);
592 Assert(cch > 0); RT_NOREF(cch);
593
594 HRESULT hrc = S_OK;
595 int vrc = RTVfsFileOpen(m->hVfsUefiVarStore, szVarPath,
596 RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
597 phVfsFile);
598 if ( vrc == VERR_PATH_NOT_FOUND
599 || vrc == VERR_FILE_NOT_FOUND)
600 {
601 /*
602 * Try to create the owner GUID of the variable by creating the appropriate directory,
603 * ignore error if it exists already.
604 */
605 RTVFSDIR hVfsDirRoot = NIL_RTVFSDIR;
606 vrc = RTVfsOpenRoot(m->hVfsUefiVarStore, &hVfsDirRoot);
607 if (RT_SUCCESS(vrc))
608 {
609 char szGuidPath[_1K];
610 cch = RTStrPrintf2(szGuidPath, sizeof(szGuidPath), "by-uuid/%RTuuid", &UuidVar);
611 Assert(cch > 0);
612
613 RTVFSDIR hVfsDirGuid = NIL_RTVFSDIR;
614 vrc = RTVfsDirCreateDir(hVfsDirRoot, szGuidPath, 0755, 0 /*fFlags*/, &hVfsDirGuid);
615 if (RT_SUCCESS(vrc))
616 RTVfsDirRelease(hVfsDirGuid);
617 else if (vrc == VERR_ALREADY_EXISTS)
618 vrc = VINF_SUCCESS;
619
620 RTVfsDirRelease(hVfsDirRoot);
621 }
622 else
623 hrc = setError(E_FAIL, tr("Opening variable storage root directory failed: %Rrc"), vrc);
624
625 if (RT_SUCCESS(vrc))
626 {
627 vrc = RTVfsFileOpen(m->hVfsUefiVarStore, szVarPath,
628 RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_CREATE,
629 phVfsFile);
630 if (RT_SUCCESS(vrc))
631 vrc = i_uefiVarStoreSetVarAttr(pszVar, fAttr);
632 }
633
634 if (RT_FAILURE(vrc))
635 hrc = setError(E_FAIL, tr("Creating the variable '%s' failed: %Rrc"), pszVar, vrc);
636 }
637
638 return hrc;
639}
640
641
642HRESULT UefiVariableStore::i_uefiVarStoreSetVar(PCEFI_GUID pGuid, const char *pszVar, uint32_t fAttr, const void *pvData, size_t cbData)
643{
644 RTVFSFILE hVfsFileVar = NIL_RTVFSFILE;
645
646 HRESULT hrc = i_uefiVarStoreAddVar(pGuid, pszVar, fAttr, &hVfsFileVar);
647 if (SUCCEEDED(hrc))
648 {
649 int vrc = RTVfsFileWrite(hVfsFileVar, pvData, cbData, NULL /*pcbWritten*/);
650 if (RT_FAILURE(vrc))
651 hrc = setError(E_FAIL, tr("Setting the variable '%s' failed: %Rrc"), pszVar, vrc);
652
653 RTVfsFileRelease(hVfsFileVar);
654 }
655
656 return hrc;
657}
658
659
660HRESULT UefiVariableStore::i_uefiVarStoreQueryVar(const char *pszVar, void *pvData, size_t cbData)
661{
662 HRESULT hrc = S_OK;
663
664 char szVarPath[_1K];
665 ssize_t cch = RTStrPrintf2(szVarPath, sizeof(szVarPath), "/by-name/%s", pszVar);
666 Assert(cch > 0); RT_NOREF(cch);
667
668 RTVFSFILE hVfsFile = NIL_RTVFSFILE;
669 int vrc = RTVfsFileOpen(m->hVfsUefiVarStore, szVarPath,
670 RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
671 &hVfsFile);
672 if (RT_SUCCESS(vrc))
673 {
674 vrc = RTVfsFileRead(hVfsFile, pvData, cbData, NULL /*pcbRead*/);
675 if (RT_FAILURE(vrc))
676 hrc = setError(E_FAIL, tr("Failed to read data of variable '%s': %Rrc"), pszVar, vrc);
677
678 RTVfsFileRelease(hVfsFile);
679 }
680 else
681 hrc = setError(E_FAIL, tr("Failed to open variable '%s' for reading: %Rrc"), pszVar, vrc);
682
683 return hrc;
684}
685
686HRESULT UefiVariableStore::i_uefiSigDbAddSig(RTEFISIGDB hEfiSigDb, const void *pvData, size_t cbData,
687 const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType)
688{
689 RTEFISIGTYPE enmSigType = RTEFISIGTYPE_INVALID;
690
691 switch (enmSignatureType)
692 {
693 case SignatureType_X509:
694 enmSigType = RTEFISIGTYPE_X509;
695 break;
696 case SignatureType_Sha256:
697 enmSigType = RTEFISIGTYPE_SHA256;
698 break;
699 default:
700 return setError(E_FAIL, tr("The given signature type is not supported"));
701 }
702
703 int vrc = RTEfiSigDbAddSignatureFromBuf(hEfiSigDb, enmSigType, aOwnerUuid.raw(), pvData, cbData);
704 if (RT_SUCCESS(vrc))
705 return S_OK;
706
707 return setError(E_FAIL, tr("Failed to add signature to the database (%Rrc)"), vrc);
708}
709
710
711HRESULT UefiVariableStore::i_uefiVarStoreAddSignatureToDb(PCEFI_GUID pGuid, const char *pszDb, const void *pvData, size_t cbData,
712 const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType)
713{
714 RTVFSFILE hVfsFileSigDb = NIL_RTVFSFILE;
715
716 HRESULT hrc = i_uefiVarStoreAddVar(pGuid, pszDb,
717 EFI_VAR_HEADER_ATTR_NON_VOLATILE
718 | EFI_VAR_HEADER_ATTR_BOOTSERVICE_ACCESS
719 | EFI_VAR_HEADER_ATTR_RUNTIME_ACCESS
720 | EFI_AUTH_VAR_HEADER_ATTR_TIME_BASED_AUTH_WRITE_ACCESS,
721 &hVfsFileSigDb);
722 if (SUCCEEDED(hrc))
723 {
724 RTEFISIGDB hEfiSigDb;
725
726 int vrc = RTEfiSigDbCreate(&hEfiSigDb);
727 if (RT_SUCCESS(vrc))
728 {
729 vrc = RTEfiSigDbAddFromExistingDb(hEfiSigDb, hVfsFileSigDb);
730 if (RT_SUCCESS(vrc))
731 {
732 hrc = i_uefiSigDbAddSig(hEfiSigDb, pvData, cbData, aOwnerUuid, enmSignatureType);
733 if (SUCCEEDED(hrc))
734 {
735 vrc = RTVfsFileSeek(hVfsFileSigDb, 0 /*offSeek*/, RTFILE_SEEK_BEGIN, NULL /*poffActual*/);
736 AssertRC(vrc);
737
738 vrc = RTEfiSigDbWriteToFile(hEfiSigDb, hVfsFileSigDb);
739 if (RT_FAILURE(vrc))
740 hrc = setError(E_FAIL, tr("Writing updated signature database failed: %Rrc"), vrc);
741 }
742 }
743 else
744 hrc = setError(E_FAIL, tr("Loading signature database failed: %Rrc"), vrc);
745
746 RTEfiSigDbDestroy(hEfiSigDb);
747 }
748 else
749 hrc = setError(E_FAIL, tr("Creating signature database failed: %Rrc"), vrc);
750
751 RTVfsFileRelease(hVfsFileSigDb);
752 }
753
754 return hrc;
755}
756
757
758HRESULT UefiVariableStore::i_uefiVarStoreAddSignatureToDbVec(PCEFI_GUID pGuid, const char *pszDb, const std::vector<BYTE> &aData,
759 const com::Guid &aOwnerUuid, SignatureType_T enmSignatureType)
760{
761 return i_uefiVarStoreAddSignatureToDb(pGuid, pszDb, &aData.front(), aData.size(), aOwnerUuid, enmSignatureType);
762}
763
764/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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