2 * Copyright 2012 <James.Bottomley@HansenPartnership.com>
6 * Install and remove a platform security2 override policy
12 #include "../refind/lib.h"
13 #include "simple_file.h"
14 #include "../include/refit_call_wrapper.h"
17 #include <security_policy.h>
20 * See the UEFI Platform Initialization manual (Vol2: DXE) for this
22 struct _EFI_SECURITY2_PROTOCOL
;
23 struct _EFI_SECURITY_PROTOCOL
;
24 struct _EFI_DEVICE_PATH_PROTOCOL
;
25 typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL
;
26 typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL
;
29 #define MSABI __attribute__((ms_abi))
34 typedef EFI_STATUS (MSABI
*EFI_SECURITY_FILE_AUTHENTICATION_STATE
) (
35 const EFI_SECURITY_PROTOCOL
*This
,
36 UINT32 AuthenticationStatus
,
37 const EFI_DEVICE_PATH_PROTOCOL
*File
39 typedef EFI_STATUS (MSABI
*EFI_SECURITY2_FILE_AUTHENTICATION
) (
40 const EFI_SECURITY2_PROTOCOL
*This
,
41 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
47 struct _EFI_SECURITY2_PROTOCOL
{
48 EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication
;
51 struct _EFI_SECURITY_PROTOCOL
{
52 EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState
;
56 static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas
= NULL
;
57 static EFI_SECURITY2_FILE_AUTHENTICATION es2fa
= NULL
;
59 // Perform shim/MOK and Secure Boot authentication on a binary that's already been
60 // loaded into memory. This function does the platform SB authentication first
61 // but preserves its return value in case of its failure, so that it can be
62 // returned in case of a shim/MOK authentication failure. This is done because
63 // the SB failure code seems to vary from one implementation to another, and I
64 // don't want to interfere with that at this time.
65 static MSABI EFI_STATUS
66 security2_policy_authentication (
67 const EFI_SECURITY2_PROTOCOL
*This
,
68 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
76 /* Chain original security policy */
77 Status
= uefi_call_wrapper(es2fa
, 5, This
, DevicePath
, FileBuffer
, FileSize
, BootPolicy
);
79 /* if OK, don't bother with MOK check */
80 if (Status
== EFI_SUCCESS
)
83 if (ShimValidate(FileBuffer
, FileSize
)) {
88 } // EFI_STATUS security2_policy_authentication()
90 // Perform both shim/MOK and platform Secure Boot authentication. This function loads
91 // the file and performs shim/MOK authentication first simply to avoid double loads
92 // of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed,
93 // since kernels are big and can take several seconds to load on some computers and
94 // filesystems. This also has the effect of returning whatever the platform code is for
95 // authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something
96 // else. (This seems to vary between implementations.)
97 static MSABI EFI_STATUS
98 security_policy_authentication (
99 const EFI_SECURITY_PROTOCOL
*This
,
100 UINT32 AuthenticationStatus
,
101 const EFI_DEVICE_PATH_PROTOCOL
*DevicePathConst
105 EFI_DEVICE_PATH
*DevPath
, *OrigDevPath
;
112 if (DevicePathConst
== NULL
) {
113 return EFI_INVALID_PARAMETER
;
115 DevPath
= OrigDevPath
= DuplicateDevicePath((EFI_DEVICE_PATH
*)DevicePathConst
);
118 Status
= refit_call3_wrapper(BS
->LocateDevicePath
, &SIMPLE_FS_PROTOCOL
, &DevPath
, &h
);
119 if (Status
!= EFI_SUCCESS
)
122 DevPathStr
= DevicePathToStr(DevPath
);
124 Status
= simple_file_open_by_handle(h
, DevPathStr
, &f
, EFI_FILE_MODE_READ
);
125 MyFreePool(DevPathStr
);
126 if (Status
!= EFI_SUCCESS
)
129 Status
= simple_file_read_all(f
, &FileSize
, &FileBuffer
);
130 simple_file_close(f
);
131 if (Status
!= EFI_SUCCESS
)
134 if (ShimValidate(FileBuffer
, FileSize
)) {
135 Status
= EFI_SUCCESS
;
137 // Try using the platform's native policy....
138 Status
= uefi_call_wrapper(esfas
, 3, This
, AuthenticationStatus
, DevicePathConst
);
140 FreePool(FileBuffer
);
143 MyFreePool(OrigDevPath
);
145 } // EFI_STATUS security_policy_authentication()
148 security_policy_install(void)
150 EFI_SECURITY_PROTOCOL
*security_protocol
;
151 EFI_SECURITY2_PROTOCOL
*security2_protocol
= NULL
;
155 /* Already Installed */
156 return EFI_ALREADY_STARTED
;
159 /* Don't bother with status here. The call is allowed
160 * to fail, since SECURITY2 was introduced in PI 1.2.1
161 * If it fails, use security2_protocol == NULL as indicator */
162 uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY2_PROTOCOL_GUID
, NULL
, (VOID
**) &security2_protocol
);
164 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY_PROTOCOL_GUID
, NULL
, (VOID
**) &security_protocol
);
165 if (status
!= EFI_SUCCESS
)
166 /* This one is mandatory, so there's a serious problem */
169 if (security2_protocol
) {
170 es2fa
= security2_protocol
->FileAuthentication
;
171 security2_protocol
->FileAuthentication
= security2_policy_authentication
;
174 esfas
= security_protocol
->FileAuthenticationState
;
175 security_protocol
->FileAuthenticationState
= security_policy_authentication
;
180 security_policy_uninstall(void)
185 EFI_SECURITY_PROTOCOL
*security_protocol
;
187 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY_PROTOCOL_GUID
, NULL
, (VOID
**) &security_protocol
);
189 if (status
!= EFI_SUCCESS
)
192 security_protocol
->FileAuthenticationState
= esfas
;
195 /* nothing installed */
196 return EFI_NOT_STARTED
;
200 EFI_SECURITY2_PROTOCOL
*security2_protocol
;
202 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY2_PROTOCOL_GUID
, NULL
, (VOID
**) &security2_protocol
);
204 if (status
!= EFI_SUCCESS
)
207 security2_protocol
->FileAuthentication
= es2fa
;