VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/ReadMe.md@ 95057

最後變更 在這個檔案從95057是 89983,由 vboxsync 提交於 4 年 前

Devices/EFI: Merge edk-stable202105 and openssl 1.1.1j and make it build, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 14.8 KB
 
1---
2title: UEFI Variable Policy Whitepaper
3version: 1.0
4copyright: Copyright (c) Microsoft Corporation.
5---
6
7# UEFI Variable Policy
8
9## Summary
10
11UEFI Variable Policy spec aims to describe the DXE protocol interface
12which allows enforcing certain rules on certain UEFI variables. The
13protocol allows communication with the Variable Policy Engine which
14performs the policy enforcement.
15
16The Variable Policy is comprised of a set of policy entries which
17describe, per UEFI variable (identified by namespace GUID and variable
18name) the following rules:
19
20- Required variable attributes
21- Prohibited variable attributes
22- Minimum variable size
23- Maximum variable size
24- Locking:
25 - Locking "immediately"
26 - Locking on creation
27 - Locking based on a state of another variable
28
29The spec assumes that the Variable Policy Engine runs in a trusted
30enclave, potentially off the main CPU that runs UEFI. For that reason,
31it is assumed that the Variable Policy Engine has no concept of UEFI
32events, and that the communication from the DXE driver to the trusted
33enclave is proprietary.
34
35At power-on, the Variable Policy Engine is:
36
37- Enabled -- present policy entries are evaluated on variable access
38 calls.
39- Unlocked -- new policy entries can be registered.
40
41Policy is expected to be clear on power-on. Policy is volatile and not
42preserved across system reset.
43
44## DXE Protocol
45
46```h
47typedef struct {
48 UINT64 Revision;
49 DISABLE_VARIABLE_POLICY DisableVariablePolicy;
50 IS_VARIABLE_POLICY_ENABLED IsVariablePolicyEnabled;
51 REGISTER_VARIABLE_POLICY RegisterVariablePolicy;
52 DUMP_VARIABLE_POLICY DumpVariablePolicy;
53 LOCK_VARIABLE_POLICY LockVariablePolicy;
54} _VARIABLE_POLICY_PROTOCOL;
55
56typedef _VARIABLE_POLICY_PROTOCOL VARIABLE_POLICY_PROTOCOL;
57
58extern EFI_GUID gVariablePolicyProtocolGuid;
59```
60
61```text
62## Include/Protocol/VariablePolicy.h
63 gVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF, { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }
64```
65
66### DisableVariablePolicy
67
68Function prototype:
69
70```c
71EFI_STATUS
72EFIAPI
73DisableVariablePolicy (
74 VOID
75 );
76```
77
78`DisableVariablePolicy` call disables the Variable Policy Engine, so
79that the present policy entries are no longer taken into account on
80variable access calls. This call effectively turns off the variable
81policy verification for this boot. This also disables UEFI
82Authenticated Variable protections including Secure Boot.
83`DisableVariablePolicy` can only be called once during boot. If called
84more than once, it will return `EFI_ALREADY_STARTED`. Note, this process
85is irreversible until the next system reset -- there is no
86"EnablePolicy" protocol function.
87
88_IMPORTANT NOTE:_ It is strongly recommended that VariablePolicy *NEVER*
89be disabled in "normal, production boot conditions". It is expected to always
90be enforced. The most likely reasons to disable are for Manufacturing and
91Refurbishing scenarios. If in doubt, leave the `gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable`
92PCD set to `FALSE` and VariablePolicy will always be enabled.
93
94### IsVariablePolicyEnabled
95
96Function prototype:
97
98```c
99EFI_STATUS
100EFIAPI
101IsVariablePolicyEnabled (
102 OUT BOOLEAN *State
103 );
104```
105
106`IsVariablePolicyEnabled` accepts a pointer to a Boolean in which it
107will store `TRUE` if Variable Policy Engine is enabled, or `FALSE` if
108Variable Policy Engine is disabled. The function returns `EFI_SUCCESS`.
109
110### RegisterVariablePolicy
111
112Function prototype:
113
114```c
115EFI_STATUS
116EFIAPI
117RegisterVariablePolicy (
118 IN CONST VARIABLE_POLICY_ENTRY *PolicyEntry
119 );
120```
121
122`RegisterVariablePolicy` call accepts a pointer to a policy entry
123structure and returns the status of policy registration. If the
124Variable Policy Engine is not locked and the policy structures are
125valid, the function will return `EFI_SUCCESS`. If the Variable Policy
126Engine is locked, `RegisterVariablePolicy` call will return
127`EFI_WRITE_PROTECTED` and will not register the policy entry. Bulk
128registration is not supported at this time due to the requirements
129around error handling on each policy registration.
130
131Upon successful registration of a policy entry, Variable Policy Engine
132will then evaluate this entry on subsequent variable access calls (as
133long as Variable Policy Engine hasn't been disabled).
134
135### DumpVariablePolicy
136
137Function prototype:
138
139```c
140EFI_STATUS
141EFIAPI
142DumpVariablePolicy (
143 OUT UINT8 *Policy,
144 IN OUT UINT32 *Size
145 );
146```
147
148`DumpVariablePolicy` call accepts a pointer to a buffer and a pointer to
149the size of the buffer as parameters and returns the status of placing
150the policy into the buffer. On first call to `DumpVariablePolicy` one
151should pass `NULL` as the buffer and a pointer to 0 as the `Size` variable
152and `DumpVariablePolicy` will return `EFI_BUFFER_TOO_SMALL` and will
153populate the `Size` parameter with the size of the needed buffer to
154store the policy. This way, the caller can allocate the buffer of
155correct size and call `DumpVariablePolicy` again. The function will
156populate the buffer with policy and return `EFI_SUCCESS`.
157
158### LockVariablePolicy
159
160Function prototype:
161
162```c
163EFI_STATUS
164EFIAPI
165LockVariablePolicy (
166 VOID
167 );
168```
169
170`LockVariablePolicy` locks the Variable Policy Engine, i.e. prevents any
171new policy entries from getting registered in this boot
172(`RegisterVariablePolicy` calls will fail with `EFI_WRITE_PROTECTED`
173status code returned).
174
175## Policy Structure
176
177The structure below is meant for the DXE protocol calling interface,
178when communicating to the Variable Policy Engine, thus the pragma pack
179directive. How these policies are stored in memory is up to the
180implementation.
181
182```c
183#pragma pack(1)
184typedef struct {
185 UINT32 Version;
186 UINT16 Size;
187 UINT16 OffsetToName;
188 EFI_GUID Namespace;
189 UINT32 MinSize;
190 UINT32 MaxSize;
191 UINT32 AttributesMustHave;
192 UINT32 AttributesCantHave;
193 UINT8 LockPolicyType;
194 UINT8 Reserved[3];
195 // UINT8 LockPolicy[]; // Variable Length Field
196 // CHAR16 Name[]; // Variable Length Field
197} VARIABLE_POLICY_ENTRY;
198```
199
200The struct `VARIABLE_POLICY_ENTRY` above describes the layout for a policy
201entry. The first element, `Size`, is the size of the policy entry, then
202followed by `OffsetToName` -- the number of bytes from the beginning of
203the struct to the name of the UEFI variable targeted by the policy
204entry. The name can contain wildcards to match more than one variable,
205more on this in the Wildcards section. The rest of the struct elements
206are self-explanatory.
207
208```cpp
209#define VARIABLE_POLICY_TYPE_NO_LOCK 0
210#define VARIABLE_POLICY_TYPE_LOCK_NOW 1
211#define VARIABLE_POLICY_TYPE_LOCK_ON_CREATE 2
212#define VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE 3
213```
214
215`LockPolicyType` can have the following values:
216
217- `VARIABLE_POLICY_TYPE_NO_LOCK` -- means that no variable locking is performed. However,
218 the attribute and size constraints are still enforced. LockPolicy
219 field is size 0.
220- `VARIABLE_POLICY_TYPE_LOCK_NOW` -- means that the variable starts being locked
221 immediately after policy entry registration. If the variable doesn't
222 exist at this point, being LockedNow means it cannot be created on
223 this boot. LockPolicy field is size 0.
224- `VARIABLE_POLICY_TYPE_LOCK_ON_CREATE` -- means that the variable starts being locked
225 after it is created. This allows for variable creation and
226 protection after LockVariablePolicy() function has been called. The
227 LockPolicy field is size 0.
228- `VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE` -- means that the Variable Policy Engine will
229 examine the state/contents of another variable to determine if the
230 variable referenced in the policy entry is locked.
231
232```c
233typedef struct {
234 EFI_GUID Namespace;
235 UINT8 Value;
236 UINT8 Reserved;
237 // CHAR16 Name[]; // Variable Length Field
238} VARIABLE_LOCK_ON_VAR_STATE_POLICY;
239```
240
241If `LockPolicyType` is `VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE`, then the final element in the
242policy entry struct is of type `VARIABLE_LOCK_ON_VAR_STATE_POLICY`, which
243lists the namespace GUID, name (no wildcards here), and value of the
244variable which state determines the locking of the variable referenced
245in the policy entry. The "locking" variable must be 1 byte in terms of
246payload size. If the Referenced variable contents match the Value of the
247`VARIABLE_LOCK_ON_VAR_STATE_POLICY` structure, the lock will be considered
248active and the target variable will be locked. If the Reference variable
249does not exist (ie. returns `EFI_NOT_FOUND`), this policy will be
250considered inactive.
251
252## Variable Name Wildcards
253
254Two types of wildcards can be used in the UEFI variable name field in a
255policy entry:
256
2571. If the Name is a zero-length array (easily checked by comparing
258 fields `Size` and `OffsetToName` -- if they're the same, then the
259 `Name` is zero-length), then all variables in the namespace specified
260 by the provided GUID are targeted by the policy entry.
2612. Character "#" in the `Name` corresponds to one numeric character
262 (0-9, A-F, a-f). For example, string "Boot####" in the `Name`
263 field of the policy entry will make it so that the policy entry will
264 target variables named "Boot0001", "Boot0002", etc.
265
266Given the above two types of wildcards, one variable can be targeted by
267more than one policy entry, thus there is a need to establish the
268precedence rule: a more specific match is applied. When a variable
269access operation is performed, Variable Policy Engine should first check
270the variable being accessed against the policy entries without
271wildcards, then with 1 wildcard, then with 2 wildcards, etc., followed
272in the end by policy entries that match the whole namespace. One can
273still imagine a situation where two policy entries with the same number
274of wildcards match the same variable -- for example, policy entries with
275Names "Boot00##" and "Boot##01" will both match variable "Boot0001".
276Such situation can (and should) be avoided by designing mutually
277exclusive Name strings with wildcards, however, if it occurs, then the
278policy entry that was registered first will be used. After the most
279specific match is selected, all other policies are ignored.
280
281## Available Testing
282
283This functionality is current supported by two kinds of tests: there is a host-based
284unit test for the core business logic (this test accompanies the `VariablePolicyLib`
285implementation that lives in `MdeModulePkg/Library`) and there is a functional test
286for the protocol and its interfaces (this test lives in the `MdeModulePkg/Test/ShellTest`
287directory).
288
289### Host-Based Unit Test
290
291There is a test that can be run as part of the Host-Based Unit Testing
292infrastructure provided by EDK2 PyTools (documented elsewhere). It will test
293all internal guarantees and is where you will find test cases for most of the
294policy matching and security of the Variable Policy Engine.
295
296### Shell-Based Functional Test
297
298This test -- [Variable Policy Functional Unit Test](https://github.com/microsoft/mu_plus/tree/release/202005/UefiTestingPkg/FunctionalSystemTests/VarPolicyUnitTestApp) -- can be built as a
299UEFI Shell application and run to validate that the Variable Policy Engine
300is correctly installed and enforcing policies on the target system.
301
302NOTE: This test _must_ be run prior to calling `DisableVariablePolicy` for all
303test cases to pass. For this reason, it is recommended to run this on a test-built
304FW for complete results, and then again on a production-built FW for release
305results.
306
307## Use Cases
308
309The below examples are hypothetical scenarios based on real-world requirements
310that demonstrate how Variable Policies could be constructed to solve various
311problems.
312
313### UEFI Setup Variables (Example 1)
314
315Variables containing values of the setup options exposed via UEFI
316menu (setup variables). These would be locked based on a state of
317another variable, "ReadyToBoot", which would be set to 1 at the
318ReadyToBoot event. Thus, the policy for the setup variables would be
319of type `LockOnVarState`, with the "ReadyToBoot" listed as the name of
320the variable, appropriate GUID listed as the namespace, and 1 as
321value. Entry into the trusted UEFI menu app doesn't signal
322ReadyToBoot, but booting to any device does, and the setup variables
323are write-protected. The "ReadyToBoot" variable would need to be
324locked-on-create. *(THIS IS ESSENTIALLY LOCK ON EVENT, BUT SINCE THE
325POLICY ENGINE IS NOT IN THE UEFI ENVIRONMENT VARIABLES ARE USED)*
326
327For example, "AllowPXEBoot" variable locked by "ReadyToBoot" variable.
328
329(NOTE: In the below example, the emphasized fields ('Namespace', 'Value', and 'Name')
330are members of the `VARIABLE_LOCK_ON_VAR_STATE_POLICY` structure.)
331
332Size | ...
333---- | ---
334OffsetToName | ...
335NameSpace | ...
336MinSize | ...
337MaxSize | ...
338AttributesMustHave | ...
339AttributesCantHave | ...
340LockPolicyType | `VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE`
341_Namespace_ | ...
342_Value_ | 1
343_Name_ | "ReadyToBoot"
344//Name | "AllowPXEBoot"
345
346### Manufacturing VPD (Example 2)
347
348Manufacturing Variable Provisioning Data (VPD) is stored in
349variables and is created while in Manufacturing (MFG) Mode. In MFG
350Mode Variable Policy Engine is disabled, thus these VPD variables
351can be created. These variables are locked with lock policy type
352`LockNow`, so that these variables can't be tampered with in Customer
353Mode. To overwrite or clear VPD, the device would need to MFG mode,
354which is standard practice for refurbishing/remanufacturing
355scenarios.
356
357Example: "DisplayPanelCalibration" variable...
358
359Size | ...
360---- | ---
361OffsetToName | ...
362NameSpace | ...
363MinSize | ...
364MaxSize | ...
365AttributesMustHave | ...
366AttributesCantHave | ...
367LockPolicyType | `VARIABLE_POLICY_TYPE_LOCK_NOW`
368// Name | "DisplayPanelCalibration"
369
370### 3rd Party Calibration Data (Example 3)
371
372Bluetooth pre-pairing variables are locked-on-create because these
373get created by an OS application when Variable Policy is in effect.
374
375Example: "KeyboardBTPairing" variable
376
377Size | ...
378---- | ---
379OffsetToName | ...
380NameSpace | ...
381MinSize | ...
382MaxSize | ...
383AttributesMustHave | ...
384AttributesCantHave | ...
385LockPolicyType | `VARIABLE_POLICY_TYPE_LOCK_ON_CREATE`
386// Name | "KeyboardBTPairing"
387
388### Software-based Variable Policy (Example 4)
389
390Example: "Boot####" variables (a name string with wildcards that
391will match variables "Boot0000" to "BootFFFF") locked by "LockBootOrder"
392variable.
393
394Size | ...
395---- | ---
396OffsetToName | ...
397NameSpace | ...
398MinSize | ...
399MaxSize | ...
400AttributesMustHave | ...
401AttributesCantHave | ...
402LockPolicyType | `VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE`
403_Namespace_ | ...
404_Value_ | 1
405_Name_ | "LockBootOrder"
406//Name | "Boot####"
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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