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) {
73 if (efivar_get_raw(&global_guid
, L
"SecureBoot", &b
, &size
) == EFI_SUCCESS
) {
83 * See the UEFI Platform Initialization manual (Vol2: DXE) for this
85 struct _EFI_SECURITY2_PROTOCOL
;
86 struct _EFI_SECURITY_PROTOCOL
;
87 struct _EFI_DEVICE_PATH_PROTOCOL
;
89 typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL
;
90 typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL
;
91 typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL
;
93 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY_FILE_AUTHENTICATION_STATE
) (
94 const EFI_SECURITY_PROTOCOL
*This
,
95 UINT32 AuthenticationStatus
,
96 const EFI_DEVICE_PATH_PROTOCOL
*File
99 typedef EFI_STATUS (EFIAPI
*EFI_SECURITY2_FILE_AUTHENTICATION
) (
100 const EFI_SECURITY2_PROTOCOL
*This
,
101 const EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
107 struct _EFI_SECURITY2_PROTOCOL
{
108 EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication
;
111 struct _EFI_SECURITY_PROTOCOL
{
112 EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState
;
115 /* Handle to the original authenticator for security1 protocol */
116 static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas
= NULL
;
118 /* Handle to the original authenticator for security2 protocol */
119 static EFI_SECURITY2_FILE_AUTHENTICATION es2fa
= NULL
;
122 * Perform shim/MOK and Secure Boot authentication on a binary that's already been
123 * loaded into memory. This function does the platform SB authentication first
124 * but preserves its return value in case of its failure, so that it can be
125 * returned in case of a shim/MOK authentication failure. This is done because
126 * the SB failure code seems to vary from one implementation to another, and I
127 * don't want to interfere with that at this time.
129 static EFIAPI EFI_STATUS
security2_policy_authentication (const EFI_SECURITY2_PROTOCOL
*this,
130 const EFI_DEVICE_PATH_PROTOCOL
*device_path
,
131 VOID
*file_buffer
, UINTN file_size
, BOOLEAN boot_policy
) {
134 /* Chain original security policy */
135 status
= uefi_call_wrapper(es2fa
, 5, this, device_path
, file_buffer
, file_size
, boot_policy
);
137 /* if OK, don't bother with MOK check */
138 if (status
== EFI_SUCCESS
)
141 if (shim_validate(file_buffer
, file_size
))
148 * Perform both shim/MOK and platform Secure Boot authentication. This function loads
149 * the file and performs shim/MOK authentication first simply to avoid double loads
150 * of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed,
151 * since kernels are big and can take several seconds to load on some computers and
152 * filesystems. This also has the effect of returning whatever the platform code is for
153 * authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something
154 * else. (This seems to vary between implementations.)
156 static EFIAPI EFI_STATUS
security_policy_authentication (const EFI_SECURITY_PROTOCOL
*this, UINT32 authentication_status
,
157 const EFI_DEVICE_PATH_PROTOCOL
*device_path_const
) {
159 EFI_DEVICE_PATH
*dev_path
;
162 CHAR8
*file_buffer
= NULL
;
164 CHAR16
*dev_path_str
;
166 if (!device_path_const
)
167 return EFI_INVALID_PARAMETER
;
169 dev_path
= DuplicateDevicePath((EFI_DEVICE_PATH
*) device_path_const
);
171 status
= uefi_call_wrapper(BS
->LocateDevicePath
, 3, (EFI_GUID
*) &simple_fs_guid
, &dev_path
, &h
);
172 if (status
!= EFI_SUCCESS
) {
177 /* No need to check return value, this already happend in efi_main() */
178 root
= LibOpenRoot(h
);
179 dev_path_str
= DevicePathToStr(dev_path
);
182 status
= file_read(root
, dev_path_str
, 0, 0, &file_buffer
, &file_size
);
183 if (EFI_ERROR(status
))
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 /* Try using the platform's native policy.... */
193 status
= uefi_call_wrapper(esfas
, 3, this, authentication_status
, device_path_const
);
194 FreePool(file_buffer
);
199 EFI_STATUS
security_policy_install(void) {
200 EFI_SECURITY_PROTOCOL
*security_protocol
;
201 EFI_SECURITY2_PROTOCOL
*security2_protocol
= NULL
;
204 /* Already Installed */
206 return EFI_ALREADY_STARTED
;
209 * Don't bother with status here. The call is allowed
210 * to fail, since SECURITY2 was introduced in PI 1.2.1.
211 * Use security2_protocol == NULL as indicator.
213 uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security2_protocol_guid
, NULL
, (VOID
**) &security2_protocol
);
215 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security_protocol_guid
, NULL
, (VOID
**) &security_protocol
);
216 /* This one is mandatory, so there's a serious problem */
217 if (status
!= EFI_SUCCESS
)
220 esfas
= security_protocol
->FileAuthenticationState
;
221 security_protocol
->FileAuthenticationState
= security_policy_authentication
;
223 if (security2_protocol
) {
224 es2fa
= security2_protocol
->FileAuthentication
;
225 security2_protocol
->FileAuthentication
= security2_policy_authentication
;
231 EFI_STATUS
security_policy_uninstall(void) {
235 EFI_SECURITY_PROTOCOL
*security_protocol
;
237 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security_protocol_guid
, NULL
, (VOID
**) &security_protocol
);
239 if (status
!= EFI_SUCCESS
)
242 security_protocol
->FileAuthenticationState
= esfas
;
245 /* nothing installed */
246 return EFI_NOT_STARTED
;
249 EFI_SECURITY2_PROTOCOL
*security2_protocol
;
251 status
= uefi_call_wrapper(BS
->LocateProtocol
, 3, (EFI_GUID
*) &security2_protocol_guid
, NULL
, (VOID
**) &security2_protocol
);
253 if (status
!= EFI_SUCCESS
)
256 security2_protocol
->FileAuthentication
= es2fa
;