1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation; either version 2.1 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * Port to systemd-boot
14 * Copyright 2017 Max Resch <resch.max@gmail.com>
16 * Security Policy Handling
17 * Copyright 2012 <James.Bottomley@HansenPartnership.com>
18 * https://github.com/mjg59/efitools
27 /* well known shim lock guid */
28 #define SHIM_LOCK_GUID
31 EFI_STATUS
__attribute__((sysv_abi
)) (*shim_verify
) (VOID
*buffer
, UINT32 size
);
33 /* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface
34 * see shim.c/shim.h and PeHeader.h in the github shim repo */
35 EFI_STATUS
__attribute__((sysv_abi
)) (*generate_hash
) (VOID
*data
, UINT32 datasize
, VOID
*context
, UINT8
*sha256hash
, UINT8
*sha1hash
);
37 EFI_STATUS
__attribute__((sysv_abi
)) (*read_header
) (VOID
*data
, UINT32 datasize
, VOID
*context
);
40 static const EFI_GUID simple_fs_guid
= SIMPLE_FILE_SYSTEM_PROTOCOL
;
41 static const EFI_GUID global_guid
= EFI_GLOBAL_VARIABLE
;
43 static const EFI_GUID security_protocol_guid
= { 0xa46423e3, 0x4617, 0x49f1, {0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } };
44 static const EFI_GUID security2_protocol_guid
= { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } };
45 static const EFI_GUID shim_lock_guid
= { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
47 BOOLEAN
shim_loaded(void) {
48 struct ShimLock
*shim_lock
;
50 return uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &shim_lock_guid
, NULL
, (VOID
**) &shim_lock
) == EFI_SUCCESS
;
53 static BOOLEAN
shim_validate(VOID
*data
, UINT32 size
) {
54 struct ShimLock
*shim_lock
;
59 if (uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &shim_lock_guid
, NULL
, (VOID
**) &shim_lock
) != EFI_SUCCESS
)
65 if (shim_lock
->shim_verify(data
, size
) == EFI_SUCCESS
)
71 BOOLEAN
secure_boot_enabled(void) {
76 if (efivar_get_raw(&global_guid
, L
"SecureBoot", &b
, &size
) == EFI_SUCCESS
) {
86 * See the UEFI Platform Initialization manual (Vol2: DXE) for this
88 struct _EFI_SECURITY2_PROTOCOL
;
89 struct _EFI_SECURITY_PROTOCOL
;
90 struct _EFI_DEVICE_PATH_PROTOCOL
;
92 typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL
;
93 typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL
;
94 typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL
;
96 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY_FILE_AUTHENTICATION_STATE
) (
97 const EFI_SECURITY_PROTOCOL
*This
,
98 UINT32 AuthenticationStatus
,
99 const EFI_DEVICE_PATH_PROTOCOL
*File
102 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY2_FILE_AUTHENTICATION
) (
103 const EFI_SECURITY2_PROTOCOL
*This
,
104 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
110 struct _EFI_SECURITY2_PROTOCOL
{
111 EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication
;
114 struct _EFI_SECURITY_PROTOCOL
{
115 EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState
;
118 /* Handle to the original authenticator for security1 protocol */
119 static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas
= NULL
;
121 /* Handle to the original authenticator for security2 protocol */
122 static EFI_SECURITY2_FILE_AUTHENTICATION es2fa
= NULL
;
125 * Perform shim/MOK and Secure Boot authentication on a binary that's already been
126 * loaded into memory. This function does the platform SB authentication first
127 * but preserves its return value in case of its failure, so that it can be
128 * returned in case of a shim/MOK authentication failure. This is done because
129 * the SB failure code seems to vary from one implementation to another, and I
130 * don't want to interfere with that at this time.
132 static EFIAPI EFI_STATUS
security2_policy_authentication (const EFI_SECURITY2_PROTOCOL
*this,
133 const EFI_DEVICE_PATH_PROTOCOL
*device_path
,
134 VOID
*file_buffer
, UINTN file_size
, BOOLEAN boot_policy
) {
137 /* Chain original security policy */
138 status
= uefi_call_wrapper(es2fa
, 5, this, device_path
, file_buffer
, file_size
, boot_policy
);
140 /* if OK, don't bother with MOK check */
141 if (status
== EFI_SUCCESS
)
144 if (shim_validate(file_buffer
, file_size
))
151 * Perform both shim/MOK and platform Secure Boot authentication. This function loads
152 * the file and performs shim/MOK authentication first simply to avoid double loads
153 * of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed,
154 * since kernels are big and can take several seconds to load on some computers and
155 * filesystems. This also has the effect of returning whatever the platform code is for
156 * authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something
157 * else. (This seems to vary between implementations.)
159 static EFIAPI EFI_STATUS
security_policy_authentication (const EFI_SECURITY_PROTOCOL
*this, UINT32 authentication_status
,
160 const EFI_DEVICE_PATH_PROTOCOL
*device_path_const
) {
162 EFI_DEVICE_PATH
*dev_path
;
165 VOID
*file_buffer
= NULL
;
167 CHAR16
*dev_path_str
;
169 if (!device_path_const
)
170 return EFI_INVALID_PARAMETER
;
172 dev_path
= DuplicateDevicePath((EFI_DEVICE_PATH
*) device_path_const
);
174 status
= uefi_call_wrapper(BS
->LocateDevicePath
, 3, (EFI_GUID
*) &simple_fs_guid
, &dev_path
, &h
);
175 if (status
!= EFI_SUCCESS
) {
180 /* No need to check return value, this already happend in efi_main() */
181 root
= LibOpenRoot(h
);
182 dev_path_str
= DevicePathToStr(dev_path
);
185 file_size
= file_read(root
, dev_path_str
, 0, 0, file_buffer
);
186 FreePool(dev_path_str
);
187 uefi_call_wrapper(root
->Close
, 1, root
);
189 if (shim_validate(file_buffer
, file_size
))
190 status
= EFI_SUCCESS
;
192 FreePool(file_buffer
);
194 /* Try using the platform's native policy.... */
195 if (status
!= EFI_SUCCESS
)
196 status
= uefi_call_wrapper(esfas
, 3, this, authentication_status
, device_path_const
);
201 EFI_STATUS
security_policy_install(void) {
202 EFI_SECURITY_PROTOCOL
*security_protocol
;
203 EFI_SECURITY2_PROTOCOL
*security2_protocol
= NULL
;
206 /* Already Installed */
208 return EFI_ALREADY_STARTED
;
211 * Don't bother with status here. The call is allowed
212 * to fail, since SECURITY2 was introduced in PI 1.2.1
213 * If it fails, use security2_protocol == NULL as indicator
215 uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security2_protocol_guid
, NULL
, (VOID
**) &security2_protocol
);
217 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security_protocol_guid
, NULL
, (VOID
**) &security_protocol
);
218 /* This one is mandatory, so there's a serious problem */
219 if (status
!= EFI_SUCCESS
)
222 if (!security2_protocol
) {
223 es2fa
= security2_protocol
->FileAuthentication
;
224 security2_protocol
->FileAuthentication
= security2_policy_authentication
;
227 esfas
= security_protocol
->FileAuthenticationState
;
228 security_protocol
->FileAuthenticationState
= security_policy_authentication
;
233 EFI_STATUS
security_policy_uninstall(void) {
237 EFI_SECURITY_PROTOCOL
*security_protocol
;
239 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security_protocol_guid
, NULL
, (VOID
**) &security_protocol
);
241 if (status
!= EFI_SUCCESS
)
244 security_protocol
->FileAuthenticationState
= esfas
;
247 /* nothing installed */
248 return EFI_NOT_STARTED
;
251 EFI_SECURITY2_PROTOCOL
*security2_protocol
;
253 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security2_protocol_guid
, NULL
, (VOID
**) &security2_protocol
);
255 if (status
!= EFI_SUCCESS
)
258 security2_protocol
->FileAuthentication
= es2fa
;