1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 * Copyright © 2017 Max Resch <resch.max@gmail.com>
6 * Security Policy Handling
7 * Copyright © 2012 <James.Bottomley@HansenPartnership.com>
8 * https://github.com/mjg59/efitools
17 /* well known shim lock guid */
18 #define SHIM_LOCK_GUID
21 EFI_STATUS
__attribute__((sysv_abi
)) (*shim_verify
) (VOID
*buffer
, UINT32 size
);
23 /* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface
24 * see shim.c/shim.h and PeHeader.h in the github shim repo */
25 EFI_STATUS
__attribute__((sysv_abi
)) (*generate_hash
) (VOID
*data
, UINT32 datasize
, VOID
*context
, UINT8
*sha256hash
, UINT8
*sha1hash
);
27 EFI_STATUS
__attribute__((sysv_abi
)) (*read_header
) (VOID
*data
, UINT32 datasize
, VOID
*context
);
30 static const EFI_GUID simple_fs_guid
= SIMPLE_FILE_SYSTEM_PROTOCOL
;
31 static const EFI_GUID global_guid
= EFI_GLOBAL_VARIABLE
;
33 static const EFI_GUID security_protocol_guid
= { 0xa46423e3, 0x4617, 0x49f1, {0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } };
34 static const EFI_GUID security2_protocol_guid
= { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } };
35 static const EFI_GUID shim_lock_guid
= { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
37 BOOLEAN
shim_loaded(void) {
38 struct ShimLock
*shim_lock
;
40 return uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &shim_lock_guid
, NULL
, (VOID
**) &shim_lock
) == EFI_SUCCESS
;
43 static BOOLEAN
shim_validate(VOID
*data
, UINT32 size
) {
44 struct ShimLock
*shim_lock
;
49 if (uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &shim_lock_guid
, NULL
, (VOID
**) &shim_lock
) != EFI_SUCCESS
)
55 return shim_lock
->shim_verify(data
, size
) == EFI_SUCCESS
;
58 BOOLEAN
secure_boot_enabled(void) {
59 _cleanup_freepool_ CHAR8
*b
= NULL
;
62 if (efivar_get_raw(&global_guid
, L
"SecureBoot", &b
, &size
) == EFI_SUCCESS
)
69 * See the UEFI Platform Initialization manual (Vol2: DXE) for this
71 struct _EFI_SECURITY2_PROTOCOL
;
72 struct _EFI_SECURITY_PROTOCOL
;
73 struct _EFI_DEVICE_PATH_PROTOCOL
;
75 typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL
;
76 typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL
;
77 typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL
;
79 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY_FILE_AUTHENTICATION_STATE
) (
80 const EFI_SECURITY_PROTOCOL
*This
,
81 UINT32 AuthenticationStatus
,
82 const EFI_DEVICE_PATH_PROTOCOL
*File
85 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY2_FILE_AUTHENTICATION
) (
86 const EFI_SECURITY2_PROTOCOL
*This
,
87 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
93 struct _EFI_SECURITY2_PROTOCOL
{
94 EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication
;
97 struct _EFI_SECURITY_PROTOCOL
{
98 EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState
;
101 /* Handle to the original authenticator for security1 protocol */
102 static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas
= NULL
;
104 /* Handle to the original authenticator for security2 protocol */
105 static EFI_SECURITY2_FILE_AUTHENTICATION es2fa
= NULL
;
108 * Perform shim/MOK and Secure Boot authentication on a binary that's already been
109 * loaded into memory. This function does the platform SB authentication first
110 * but preserves its return value in case of its failure, so that it can be
111 * returned in case of a shim/MOK authentication failure. This is done because
112 * the SB failure code seems to vary from one implementation to another, and I
113 * don't want to interfere with that at this time.
115 static EFIAPI EFI_STATUS
security2_policy_authentication (const EFI_SECURITY2_PROTOCOL
*this,
116 const EFI_DEVICE_PATH_PROTOCOL
*device_path
,
117 VOID
*file_buffer
, UINTN file_size
, BOOLEAN boot_policy
) {
120 /* Chain original security policy */
121 status
= uefi_call_wrapper(es2fa
, 5, this, device_path
, file_buffer
, file_size
, boot_policy
);
123 /* if OK, don't bother with MOK check */
124 if (status
== EFI_SUCCESS
)
127 if (shim_validate(file_buffer
, file_size
))
134 * Perform both shim/MOK and platform Secure Boot authentication. This function loads
135 * the file and performs shim/MOK authentication first simply to avoid double loads
136 * of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed,
137 * since kernels are big and can take several seconds to load on some computers and
138 * filesystems. This also has the effect of returning whatever the platform code is for
139 * authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something
140 * else. (This seems to vary between implementations.)
142 static EFIAPI EFI_STATUS
security_policy_authentication (const EFI_SECURITY_PROTOCOL
*this, UINT32 authentication_status
,
143 const EFI_DEVICE_PATH_PROTOCOL
*device_path_const
) {
145 _cleanup_freepool_ EFI_DEVICE_PATH
*dev_path
= NULL
;
146 _cleanup_freepool_ CHAR16
*dev_path_str
= NULL
;
149 _cleanup_freepool_ CHAR8
*file_buffer
= NULL
;
152 if (!device_path_const
)
153 return EFI_INVALID_PARAMETER
;
155 dev_path
= DuplicateDevicePath((EFI_DEVICE_PATH
*) device_path_const
);
157 status
= uefi_call_wrapper(BS
->LocateDevicePath
, 3, (EFI_GUID
*) &simple_fs_guid
, &dev_path
, &h
);
158 if (status
!= EFI_SUCCESS
)
161 /* No need to check return value, this already happend in efi_main() */
162 root
= LibOpenRoot(h
);
163 dev_path_str
= DevicePathToStr(dev_path
);
165 status
= file_read(root
, dev_path_str
, 0, 0, &file_buffer
, &file_size
);
166 if (EFI_ERROR(status
))
168 uefi_call_wrapper(root
->Close
, 1, root
);
170 if (shim_validate(file_buffer
, file_size
))
173 /* Try using the platform's native policy.... */
174 return uefi_call_wrapper(esfas
, 3, this, authentication_status
, device_path_const
);
177 EFI_STATUS
security_policy_install(void) {
178 EFI_SECURITY_PROTOCOL
*security_protocol
;
179 EFI_SECURITY2_PROTOCOL
*security2_protocol
= NULL
;
182 /* Already Installed */
184 return EFI_ALREADY_STARTED
;
187 * Don't bother with status here. The call is allowed
188 * to fail, since SECURITY2 was introduced in PI 1.2.1.
189 * Use security2_protocol == NULL as indicator.
191 uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security2_protocol_guid
, NULL
, (VOID
**) &security2_protocol
);
193 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security_protocol_guid
, NULL
, (VOID
**) &security_protocol
);
194 /* This one is mandatory, so there's a serious problem */
195 if (status
!= EFI_SUCCESS
)
198 esfas
= security_protocol
->FileAuthenticationState
;
199 security_protocol
->FileAuthenticationState
= security_policy_authentication
;
201 if (security2_protocol
) {
202 es2fa
= security2_protocol
->FileAuthentication
;
203 security2_protocol
->FileAuthentication
= security2_policy_authentication
;