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 return shim_lock
->shim_verify(data
, size
) == EFI_SUCCESS
;
68 BOOLEAN
secure_boot_enabled(void) {
69 _cleanup_freepool_ CHAR8
*b
= NULL
;
72 if (efivar_get_raw(&global_guid
, L
"SecureBoot", &b
, &size
) == EFI_SUCCESS
)
79 * See the UEFI Platform Initialization manual (Vol2: DXE) for this
81 struct _EFI_SECURITY2_PROTOCOL
;
82 struct _EFI_SECURITY_PROTOCOL
;
83 struct _EFI_DEVICE_PATH_PROTOCOL
;
85 typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL
;
86 typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL
;
87 typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL
;
89 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY_FILE_AUTHENTICATION_STATE
) (
90 const EFI_SECURITY_PROTOCOL
*This
,
91 UINT32 AuthenticationStatus
,
92 const EFI_DEVICE_PATH_PROTOCOL
*File
95 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY2_FILE_AUTHENTICATION
) (
96 const EFI_SECURITY2_PROTOCOL
*This
,
97 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
103 struct _EFI_SECURITY2_PROTOCOL
{
104 EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication
;
107 struct _EFI_SECURITY_PROTOCOL
{
108 EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState
;
111 /* Handle to the original authenticator for security1 protocol */
112 static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas
= NULL
;
114 /* Handle to the original authenticator for security2 protocol */
115 static EFI_SECURITY2_FILE_AUTHENTICATION es2fa
= NULL
;
118 * Perform shim/MOK and Secure Boot authentication on a binary that's already been
119 * loaded into memory. This function does the platform SB authentication first
120 * but preserves its return value in case of its failure, so that it can be
121 * returned in case of a shim/MOK authentication failure. This is done because
122 * the SB failure code seems to vary from one implementation to another, and I
123 * don't want to interfere with that at this time.
125 static EFIAPI EFI_STATUS
security2_policy_authentication (const EFI_SECURITY2_PROTOCOL
*this,
126 const EFI_DEVICE_PATH_PROTOCOL
*device_path
,
127 VOID
*file_buffer
, UINTN file_size
, BOOLEAN boot_policy
) {
130 /* Chain original security policy */
131 status
= uefi_call_wrapper(es2fa
, 5, this, device_path
, file_buffer
, file_size
, boot_policy
);
133 /* if OK, don't bother with MOK check */
134 if (status
== EFI_SUCCESS
)
137 if (shim_validate(file_buffer
, file_size
))
144 * Perform both shim/MOK and platform Secure Boot authentication. This function loads
145 * the file and performs shim/MOK authentication first simply to avoid double loads
146 * of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed,
147 * since kernels are big and can take several seconds to load on some computers and
148 * filesystems. This also has the effect of returning whatever the platform code is for
149 * authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something
150 * else. (This seems to vary between implementations.)
152 static EFIAPI EFI_STATUS
security_policy_authentication (const EFI_SECURITY_PROTOCOL
*this, UINT32 authentication_status
,
153 const EFI_DEVICE_PATH_PROTOCOL
*device_path_const
) {
155 _cleanup_freepool_ EFI_DEVICE_PATH
*dev_path
= NULL
;
156 _cleanup_freepool_ CHAR16
*dev_path_str
= NULL
;
159 _cleanup_freepool_ CHAR8
*file_buffer
= NULL
;
162 if (!device_path_const
)
163 return EFI_INVALID_PARAMETER
;
165 dev_path
= DuplicateDevicePath((EFI_DEVICE_PATH
*) device_path_const
);
167 status
= uefi_call_wrapper(BS
->LocateDevicePath
, 3, (EFI_GUID
*) &simple_fs_guid
, &dev_path
, &h
);
168 if (status
!= EFI_SUCCESS
)
171 /* No need to check return value, this already happend in efi_main() */
172 root
= LibOpenRoot(h
);
173 dev_path_str
= DevicePathToStr(dev_path
);
175 status
= file_read(root
, dev_path_str
, 0, 0, &file_buffer
, &file_size
);
176 if (EFI_ERROR(status
))
178 uefi_call_wrapper(root
->Close
, 1, root
);
180 if (shim_validate(file_buffer
, file_size
))
183 /* Try using the platform's native policy.... */
184 return uefi_call_wrapper(esfas
, 3, this, authentication_status
, device_path_const
);
187 EFI_STATUS
security_policy_install(void) {
188 EFI_SECURITY_PROTOCOL
*security_protocol
;
189 EFI_SECURITY2_PROTOCOL
*security2_protocol
= NULL
;
192 /* Already Installed */
194 return EFI_ALREADY_STARTED
;
197 * Don't bother with status here. The call is allowed
198 * to fail, since SECURITY2 was introduced in PI 1.2.1.
199 * Use security2_protocol == NULL as indicator.
201 uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security2_protocol_guid
, NULL
, (VOID
**) &security2_protocol
);
203 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security_protocol_guid
, NULL
, (VOID
**) &security_protocol
);
204 /* This one is mandatory, so there's a serious problem */
205 if (status
!= EFI_SUCCESS
)
208 esfas
= security_protocol
->FileAuthenticationState
;
209 security_protocol
->FileAuthenticationState
= security_policy_authentication
;
211 if (security2_protocol
) {
212 es2fa
= security2_protocol
->FileAuthentication
;
213 security2_protocol
->FileAuthentication
= security2_policy_authentication
;
219 EFI_STATUS
security_policy_uninstall(void) {
223 EFI_SECURITY_PROTOCOL
*security_protocol
;
225 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security_protocol_guid
, NULL
, (VOID
**) &security_protocol
);
227 if (status
!= EFI_SUCCESS
)
230 security_protocol
->FileAuthenticationState
= esfas
;
233 /* nothing installed */
234 return EFI_NOT_STARTED
;
237 EFI_SECURITY2_PROTOCOL
*security2_protocol
;
239 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security2_protocol_guid
, NULL
, (VOID
**) &security2_protocol
);
241 if (status
!= EFI_SUCCESS
)
244 security2_protocol
->FileAuthentication
= es2fa
;