1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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
14 #include "missing_efi.h"
18 #if defined(__x86_64__) || defined(__i386__)
19 #define __sysv_abi__ __attribute__((sysv_abi))
25 EFI_STATUS
__sysv_abi__ (*shim_verify
) (void *buffer
, uint32_t size
);
27 /* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface
28 * see shim.c/shim.h and PeHeader.h in the github shim repo */
29 EFI_STATUS
__sysv_abi__ (*generate_hash
) (void *data
, uint32_t datasize
, void *context
, uint8_t *sha256hash
, uint8_t *sha1hash
);
31 EFI_STATUS
__sysv_abi__ (*read_header
) (void *data
, uint32_t datasize
, void *context
);
34 #define SHIM_LOCK_GUID \
35 &(const EFI_GUID) { 0x605dab50, 0xe046, 0x4300, { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } }
37 BOOLEAN
shim_loaded(void) {
38 struct ShimLock
*shim_lock
;
40 return BS
->LocateProtocol((EFI_GUID
*) SHIM_LOCK_GUID
, NULL
, (void**) &shim_lock
) == EFI_SUCCESS
;
43 static BOOLEAN
shim_validate(void *data
, uint32_t size
) {
44 struct ShimLock
*shim_lock
;
49 if (BS
->LocateProtocol((EFI_GUID
*) SHIM_LOCK_GUID
, NULL
, (void**) &shim_lock
) != EFI_SUCCESS
)
55 return shim_lock
->shim_verify(data
, size
) == EFI_SUCCESS
;
58 /* Handle to the original authenticator for security1 protocol */
59 static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas
= NULL
;
61 /* Handle to the original authenticator for security2 protocol */
62 static EFI_SECURITY2_FILE_AUTHENTICATION es2fa
= NULL
;
65 * Perform shim/MOK and Secure Boot authentication on a binary that's already been
66 * loaded into memory. This function does the platform SB authentication first
67 * but preserves its return value in case of its failure, so that it can be
68 * returned in case of a shim/MOK authentication failure. This is done because
69 * the SB failure code seems to vary from one implementation to another, and I
70 * don't want to interfere with that at this time.
72 static EFIAPI EFI_STATUS
security2_policy_authentication (const EFI_SECURITY2_PROTOCOL
*this,
73 const EFI_DEVICE_PATH_PROTOCOL
*device_path
,
74 void *file_buffer
, UINTN file_size
, BOOLEAN boot_policy
) {
78 /* device_path and file_buffer may be NULL */
80 /* Chain original security policy */
81 err
= es2fa(this, device_path
, file_buffer
, file_size
, boot_policy
);
83 /* if OK, don't bother with MOK check */
84 if (err
== EFI_SUCCESS
)
87 if (shim_validate(file_buffer
, file_size
))
94 * Perform both shim/MOK and platform Secure Boot authentication. This function loads
95 * the file and performs shim/MOK authentication first simply to avoid double loads
96 * of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed,
97 * since kernels are big and can take several seconds to load on some computers and
98 * filesystems. This also has the effect of returning whatever the platform code is for
99 * authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something
100 * else. (This seems to vary between implementations.)
102 static EFIAPI EFI_STATUS
security_policy_authentication (const EFI_SECURITY_PROTOCOL
*this, uint32_t authentication_status
,
103 const EFI_DEVICE_PATH_PROTOCOL
*device_path_const
) {
105 _cleanup_free_ char16_t
*dev_path_str
= NULL
;
107 _cleanup_free_
char *file_buffer
= NULL
;
112 if (!device_path_const
)
113 return EFI_INVALID_PARAMETER
;
115 EFI_DEVICE_PATH
*dp
= (EFI_DEVICE_PATH
*) device_path_const
;
116 err
= BS
->LocateDevicePath(&FileSystemProtocol
, &dp
, &h
);
117 if (err
!= EFI_SUCCESS
)
120 _cleanup_(file_closep
) EFI_FILE
*root
= NULL
;
121 err
= open_volume(h
, &root
);
122 if (err
!= EFI_SUCCESS
)
125 dev_path_str
= DevicePathToStr(dp
);
127 return EFI_OUT_OF_RESOURCES
;
129 err
= file_read(root
, dev_path_str
, 0, 0, &file_buffer
, &file_size
);
130 if (err
!= EFI_SUCCESS
)
133 if (shim_validate(file_buffer
, file_size
))
136 /* Try using the platform's native policy.... */
137 return esfas(this, authentication_status
, device_path_const
);
140 EFI_STATUS
security_policy_install(void) {
141 EFI_SECURITY_PROTOCOL
*security_protocol
;
142 EFI_SECURITY2_PROTOCOL
*security2_protocol
= NULL
;
145 /* Already Installed */
147 return EFI_ALREADY_STARTED
;
150 * Don't bother with status here. The call is allowed
151 * to fail, since SECURITY2 was introduced in PI 1.2.1.
152 * Use security2_protocol == NULL as indicator.
154 BS
->LocateProtocol((EFI_GUID
*) SECURITY_PROTOCOL2_GUID
, NULL
, (void**) &security2_protocol
);
156 err
= BS
->LocateProtocol((EFI_GUID
*) SECURITY_PROTOCOL_GUID
, NULL
, (void**) &security_protocol
);
157 /* This one is mandatory, so there's a serious problem */
158 if (err
!= EFI_SUCCESS
)
161 esfas
= security_protocol
->FileAuthenticationState
;
162 security_protocol
->FileAuthenticationState
= security_policy_authentication
;
164 if (security2_protocol
) {
165 es2fa
= security2_protocol
->FileAuthentication
;
166 security2_protocol
->FileAuthentication
= security2_policy_authentication
;