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
;
27 #ifdef __MAKEWITH_GNUEFI
28 typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL
;
32 #define MSABI __attribute__((ms_abi))
37 typedef EFI_STATUS (MSABI
*EFI_SECURITY_FILE_AUTHENTICATION_STATE
) (
38 const EFI_SECURITY_PROTOCOL
*This
,
39 UINT32 AuthenticationStatus
,
40 const EFI_DEVICE_PATH_PROTOCOL
*File
42 typedef EFI_STATUS (MSABI
*EFI_SECURITY2_FILE_AUTHENTICATION
) (
43 const EFI_SECURITY2_PROTOCOL
*This
,
44 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
50 struct _EFI_SECURITY2_PROTOCOL
{
51 EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication
;
54 struct _EFI_SECURITY_PROTOCOL
{
55 EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState
;
59 static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas
= NULL
;
60 static EFI_SECURITY2_FILE_AUTHENTICATION es2fa
= NULL
;
62 // Perform shim/MOK and Secure Boot authentication on a binary that's already been
63 // loaded into memory. This function does the platform SB authentication first
64 // but preserves its return value in case of its failure, so that it can be
65 // returned in case of a shim/MOK authentication failure. This is done because
66 // the SB failure code seems to vary from one implementation to another, and I
67 // don't want to interfere with that at this time.
68 static MSABI EFI_STATUS
69 security2_policy_authentication (
70 const EFI_SECURITY2_PROTOCOL
*This
,
71 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
79 /* Chain original security policy */
80 Status
= uefi_call_wrapper(es2fa
, 5, This
, DevicePath
, FileBuffer
, FileSize
, BootPolicy
);
82 /* if OK, don't bother with MOK check */
83 if (Status
== EFI_SUCCESS
)
86 if (ShimValidate(FileBuffer
, FileSize
)) {
91 } // EFI_STATUS security2_policy_authentication()
93 // Perform both shim/MOK and platform Secure Boot authentication. This function loads
94 // the file and performs shim/MOK authentication first simply to avoid double loads
95 // of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed,
96 // since kernels are big and can take several seconds to load on some computers and
97 // filesystems. This also has the effect of returning whatever the platform code is for
98 // authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something
99 // else. (This seems to vary between implementations.)
100 static MSABI EFI_STATUS
101 security_policy_authentication (
102 const EFI_SECURITY_PROTOCOL
*This
,
103 UINT32 AuthenticationStatus
,
104 const EFI_DEVICE_PATH_PROTOCOL
*DevicePathConst
108 EFI_DEVICE_PATH
*DevPath
, *OrigDevPath
;
115 if (DevicePathConst
== NULL
) {
116 return EFI_INVALID_PARAMETER
;
118 DevPath
= OrigDevPath
= DuplicateDevicePath((EFI_DEVICE_PATH
*)DevicePathConst
);
121 Status
= refit_call3_wrapper(BS
->LocateDevicePath
, &SIMPLE_FS_PROTOCOL
, &DevPath
, &h
);
122 if (Status
!= EFI_SUCCESS
)
125 DevPathStr
= DevicePathToStr(DevPath
);
127 Status
= simple_file_open_by_handle(h
, DevPathStr
, &f
, EFI_FILE_MODE_READ
);
128 MyFreePool(DevPathStr
);
129 if (Status
!= EFI_SUCCESS
)
132 Status
= simple_file_read_all(f
, &FileSize
, &FileBuffer
);
133 simple_file_close(f
);
134 if (Status
!= EFI_SUCCESS
)
137 if (ShimValidate(FileBuffer
, FileSize
)) {
138 Status
= EFI_SUCCESS
;
140 // Try using the platform's native policy....
141 Status
= uefi_call_wrapper(esfas
, 3, This
, AuthenticationStatus
, DevicePathConst
);
143 FreePool(FileBuffer
);
146 MyFreePool(OrigDevPath
);
148 } // EFI_STATUS security_policy_authentication()
151 security_policy_install(void)
153 EFI_SECURITY_PROTOCOL
*security_protocol
;
154 EFI_SECURITY2_PROTOCOL
*security2_protocol
= NULL
;
158 /* Already Installed */
159 return EFI_ALREADY_STARTED
;
162 /* Don't bother with status here. The call is allowed
163 * to fail, since SECURITY2 was introduced in PI 1.2.1
164 * If it fails, use security2_protocol == NULL as indicator */
165 uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY2_PROTOCOL_GUID
, NULL
, (VOID
**) &security2_protocol
);
167 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY_PROTOCOL_GUID
, NULL
, (VOID
**) &security_protocol
);
168 if (status
!= EFI_SUCCESS
)
169 /* This one is mandatory, so there's a serious problem */
172 if (security2_protocol
) {
173 es2fa
= security2_protocol
->FileAuthentication
;
174 security2_protocol
->FileAuthentication
= security2_policy_authentication
;
177 esfas
= security_protocol
->FileAuthenticationState
;
178 security_protocol
->FileAuthenticationState
= security_policy_authentication
;
183 security_policy_uninstall(void)
188 EFI_SECURITY_PROTOCOL
*security_protocol
;
190 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY_PROTOCOL_GUID
, NULL
, (VOID
**) &security_protocol
);
192 if (status
!= EFI_SUCCESS
)
195 security_protocol
->FileAuthenticationState
= esfas
;
198 /* nothing installed */
199 return EFI_NOT_STARTED
;
203 EFI_SECURITY2_PROTOCOL
*security2_protocol
;
205 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, &SECURITY2_PROTOCOL_GUID
, NULL
, (VOID
**) &security2_protocol
);
207 if (status
!= EFI_SUCCESS
)
210 security2_protocol
->FileAuthentication
= es2fa
;