2 * Copyright 2012 <James.Bottomley@HansenPartnership.com>
6 * Install and remove a platform security2 override policy
10 // #include <efilib.h>
15 //#include "variables.h"
16 #include "simple_file.h"
18 #include "../include/refit_call_wrapper.h"
21 #include <security_policy.h>
24 * See the UEFI Platform Initialization manual (Vol2: DXE) for this
26 struct _EFI_SECURITY2_PROTOCOL
;
27 struct _EFI_SECURITY_PROTOCOL
;
28 struct _EFI_DEVICE_PATH_PROTOCOL
;
29 typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL
;
30 typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL
;
31 #ifdef __MAKEWITH_GNUEFI
32 typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL
;
35 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY_FILE_AUTHENTICATION_STATE
) (
36 const EFI_SECURITY_PROTOCOL
*This
,
37 UINT32 AuthenticationStatus
,
38 const EFI_DEVICE_PATH_PROTOCOL
*File
40 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY2_FILE_AUTHENTICATION
) (
41 const EFI_SECURITY2_PROTOCOL
*This
,
42 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
48 struct _EFI_SECURITY2_PROTOCOL
{
49 EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication
;
52 struct _EFI_SECURITY_PROTOCOL
{
53 EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState
;
57 static UINT8
*security_policy_esl
= NULL
;
58 static UINTN security_policy_esl_len
;
60 static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas
= NULL
;
61 static EFI_SECURITY2_FILE_AUTHENTICATION es2fa
= NULL
;
63 #ifdef __MAKEWITH_GNUEFI
64 static EFI_STATUS
thunk_security_policy_authentication(
65 const EFI_SECURITY_PROTOCOL
*This
,
66 UINT32 AuthenticationStatus
,
67 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
69 __attribute__((unused
));
71 static EFI_STATUS
thunk_security2_policy_authentication(
72 const EFI_SECURITY2_PROTOCOL
*This
,
73 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
78 __attribute__((unused
));
81 #ifdef __MAKEWITH_GNUEFI
82 static __attribute__((used
)) EFI_STATUS
84 static __attribute__((ms_abi
)) EFI_STATUS
86 security2_policy_authentication (
87 const EFI_SECURITY2_PROTOCOL
*This
,
88 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
96 /* Chain original security policy */
97 status
= uefi_call_wrapper(es2fa
, 5, This
, DevicePath
, FileBuffer
, FileSize
, BootPolicy
);
99 /* if OK, don't bother with MOK check */
100 if (status
== EFI_SUCCESS
)
103 if (ShimValidate(FileBuffer
, FileSize
)) {
104 status
= EFI_SUCCESS
;
106 status
= EFI_ACCESS_DENIED
;
109 // status = security_policy_check_mok(FileBuffer, FileSize);
114 #ifdef __MAKEWITH_GNUEFI
115 static __attribute__((used
)) EFI_STATUS
117 static __attribute__((ms_abi
)) EFI_STATUS
119 security_policy_authentication (
120 const EFI_SECURITY_PROTOCOL
*This
,
121 UINT32 AuthenticationStatus
,
122 const EFI_DEVICE_PATH_PROTOCOL
*DevicePathConst
126 EFI_DEVICE_PATH
*DevPath
127 = DuplicateDevicePath((EFI_DEVICE_PATH
*)DevicePathConst
),
128 *OrigDevPath
= DevPath
;
135 /* Chain original security policy */
136 status
= refit_call3_wrapper(esfas
, This
, AuthenticationStatus
, DevicePathConst
);
138 /* if OK avoid checking MOK: It's a bit expensive to
139 * read the whole file in again (esfas already did this) */
140 if (status
== EFI_SUCCESS
)
143 status
= refit_call3_wrapper(BS
->LocateDevicePath
, &SIMPLE_FS_PROTOCOL
, &DevPath
, &h
);
144 if (status
!= EFI_SUCCESS
)
147 DevPathStr
= DevicePathToStr(DevPath
);
149 status
= simple_file_open_by_handle(h
, DevPathStr
, &f
, EFI_FILE_MODE_READ
);
150 FreePool(DevPathStr
);
151 if (status
!= EFI_SUCCESS
)
154 status
= simple_file_read_all(f
, &FileSize
, &FileBuffer
);
155 simple_file_close(f
);
156 if (status
!= EFI_SUCCESS
)
159 if (ShimValidate(FileBuffer
, FileSize
)) {
160 status
= EFI_SUCCESS
;
162 status
= EFI_ACCESS_DENIED
;
164 FreePool(FileBuffer
);
167 FreePool(OrigDevPath
);
171 #ifdef __MAKEWITH_GNUEFI
172 /* Nasty: ELF and EFI have different calling conventions. Here is the map for
175 * 1) rdi -> rcx (32 saved)
176 * 2) rsi -> rdx (32 saved)
177 * 3) rdx -> r8 ( 32 saved)
178 * 4) rcx -> r9 (32 saved)
179 * 5) r8 -> 32(%rsp) (48 saved)
180 * 6) r9 -> 40(%rsp) (48 saved)
181 * 7) pad+0(%rsp) -> 48(%rsp) (64 saved)
182 * 8) pad+8(%rsp) -> 56(%rsp) (64 saved)
183 * 9) pad+16(%rsp) -> 64(%rsp) (80 saved)
184 * 10) pad+24(%rsp) -> 72(%rsp) (80 saved)
185 * 11) pad+32(%rsp) -> 80(%rsp) (96 saved)
188 * So for a five argument callback, the map is ignore the first two arguments
189 * and then map (EFI -> ELF) assuming pad = 0.
197 * Calling conventions also differ over volatile and preserved registers in
198 * MS: RBX, RBP, RDI, RSI, R12, R13, R14, and R15 are considered nonvolatile .
199 * In ELF: Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling
200 * function and the called function is required to preserve their values.
202 * This means when accepting a function callback from MS -> ELF, we have to do
203 * separate preservation on %rdi, %rsi before swizzling the arguments and
204 * handing off to the ELF function.
208 ".type security2_policy_authentication,@function\n"
209 "thunk_security2_policy_authentication:\n\t"
210 "mov 0x28(%rsp), %r10 # ARG5\n\t"
214 "subq $8, %rsp # space for storing stack pad\n\t"
215 "mov $0x08, %rax\n\t"
216 "mov $0x10, %r10\n\t"
218 "cmovnz %rax, %r11\n\t"
219 "cmovz %r10, %r11\n\t"
220 "subq %r11, %rsp\n\t"
222 "mov %r11, (%rsp)\n\t"
223 "# five argument swizzle\n\t"
230 "callq security2_policy_authentication@PLT\n\t"
231 "mov (%rsp), %r11\n\t"
232 "addq %r11, %rsp\n\t"
239 ".type security_policy_authentication,@function\n"
240 "thunk_security_policy_authentication:\n\t"
243 "subq $8, %rsp # space for storing stack pad\n\t"
244 "mov $0x08, %rax\n\t"
245 "mov $0x10, %r10\n\t"
247 "cmovnz %rax, %r11\n\t"
248 "cmovz %r10, %r11\n\t"
249 "subq %r11, %rsp\n\t"
251 "mov %r11, (%rsp)\n\t"
252 "# three argument swizzle\n\t"
256 "callq security_policy_authentication@PLT\n\t"
257 "mov (%rsp), %r11\n\t"
258 "addq %r11, %rsp\n\t"
266 security_policy_install(void)
268 EFI_SECURITY_PROTOCOL
*security_protocol
;
269 EFI_SECURITY2_PROTOCOL
*security2_protocol
= NULL
;
273 /* Already Installed */
274 return EFI_ALREADY_STARTED
;
277 /* Don't bother with status here. The call is allowed
278 * to fail, since SECURITY2 was introduced in PI 1.2.1
279 * If it fails, use security2_protocol == NULL as indicator */
280 uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY2_PROTOCOL_GUID
, NULL
, (VOID
**) &security2_protocol
);
282 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY_PROTOCOL_GUID
, NULL
, (VOID
**) &security_protocol
);
283 if (status
!= EFI_SUCCESS
)
284 /* This one is mandatory, so there's a serious problem */
287 if (security2_protocol
) {
288 es2fa
= security2_protocol
->FileAuthentication
;
289 #ifdef __MAKEWITH_GNUEFI
290 security2_protocol
->FileAuthentication
= thunk_security2_policy_authentication
;
292 security2_protocol
->FileAuthentication
= security2_policy_authentication
;
296 esfas
= security_protocol
->FileAuthenticationState
;
297 #ifdef __MAKEWITH_GNUEFI
298 security_protocol
->FileAuthenticationState
= thunk_security_policy_authentication
;
300 security_protocol
->FileAuthenticationState
= security_policy_authentication
;
306 security_policy_uninstall(void)
311 EFI_SECURITY_PROTOCOL
*security_protocol
;
313 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3,
314 &SECURITY_PROTOCOL_GUID
, NULL
,
315 (VOID
**) &security_protocol
);
317 if (status
!= EFI_SUCCESS
)
320 security_protocol
->FileAuthenticationState
= esfas
;
323 /* nothing installed */
324 return EFI_NOT_STARTED
;
328 EFI_SECURITY2_PROTOCOL
*security2_protocol
;
330 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3,
331 &SECURITY2_PROTOCOL_GUID
, NULL
,
332 (VOID
**) &security2_protocol
);
334 if (status
!= EFI_SUCCESS
)
337 security2_protocol
->FileAuthentication
= es2fa
;
345 security_protocol_set_hashes(unsigned char *esl
, int len
)
347 security_policy_esl
= esl
;
348 security_policy_esl_len
= len
;