X-Git-Url: https://code.delx.au/refind/blobdiff_plain/7e22a0b1a85d3403ed76ece8339a07ef59174ed3..37c98e1a4e30f80d6a7f7158bc27c81a1c3cac37:/mok/security_policy.c diff --git a/mok/security_policy.c b/mok/security_policy.c index 086ef6a..33d3be7 100644 --- a/mok/security_policy.c +++ b/mok/security_policy.c @@ -6,15 +6,11 @@ * Install and remove a platform security2 override policy */ -// #include -// #include #include #include "guid.h" -//#include "sha256.h" -//#include "variables.h" +#include "../refind/lib.h" #include "simple_file.h" -//#include "errors.h" #include "../include/refit_call_wrapper.h" #include "mok.h" @@ -28,16 +24,19 @@ struct _EFI_SECURITY_PROTOCOL; struct _EFI_DEVICE_PATH_PROTOCOL; typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL; typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL; -#ifdef __MAKEWITH_GNUEFI -typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL; + +#if defined(EFIX64) +#define MSABI __attribute__((ms_abi)) +#else +#define MSABI #endif -typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) ( +typedef EFI_STATUS (MSABI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) ( const EFI_SECURITY_PROTOCOL *This, UINT32 AuthenticationStatus, const EFI_DEVICE_PATH_PROTOCOL *File ); -typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) ( +typedef EFI_STATUS (MSABI *EFI_SECURITY2_FILE_AUTHENTICATION) ( const EFI_SECURITY2_PROTOCOL *This, const EFI_DEVICE_PATH_PROTOCOL *DevicePath, VOID *FileBuffer, @@ -54,35 +53,16 @@ struct _EFI_SECURITY_PROTOCOL { }; -static UINT8 *security_policy_esl = NULL; -static UINTN security_policy_esl_len; - static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL; static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL; -#ifdef __MAKEWITH_GNUEFI -static EFI_STATUS thunk_security_policy_authentication( - const EFI_SECURITY_PROTOCOL *This, - UINT32 AuthenticationStatus, - const EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -__attribute__((unused)); - -static EFI_STATUS thunk_security2_policy_authentication( - const EFI_SECURITY2_PROTOCOL *This, - const EFI_DEVICE_PATH_PROTOCOL *DevicePath, - VOID *FileBuffer, - UINTN FileSize, - BOOLEAN BootPolicy - ) -__attribute__((unused)); -#endif - -#ifdef __MAKEWITH_GNUEFI -static __attribute__((used)) EFI_STATUS -#else -static __attribute__((ms_abi)) EFI_STATUS -#endif +// Perform shim/MOK and Secure Boot authentication on a binary that's already been +// loaded into memory. This function does the platform SB authentication first +// but preserves its return value in case of its failure, so that it can be +// returned in case of a shim/MOK authentication failure. This is done because +// the SB failure code seems to vary from one implementation to another, and I +// don't want to interfere with that at this time. +static MSABI EFI_STATUS security2_policy_authentication ( const EFI_SECURITY2_PROTOCOL *This, const EFI_DEVICE_PATH_PROTOCOL *DevicePath, @@ -91,176 +71,78 @@ security2_policy_authentication ( BOOLEAN BootPolicy ) { - EFI_STATUS status; + EFI_STATUS Status; /* Chain original security policy */ - status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer, FileSize, BootPolicy); + Status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer, FileSize, BootPolicy); /* if OK, don't bother with MOK check */ - if (status == EFI_SUCCESS) - return status; + if (Status == EFI_SUCCESS) + return Status; if (ShimValidate(FileBuffer, FileSize)) { - status = EFI_SUCCESS; + return EFI_SUCCESS; } else { - status = EFI_ACCESS_DENIED; + return Status; } - -// status = security_policy_check_mok(FileBuffer, FileSize); - - return status; -} - -#ifdef __MAKEWITH_GNUEFI -static __attribute__((used)) EFI_STATUS -#else -static __attribute__((ms_abi)) EFI_STATUS -#endif +} // EFI_STATUS security2_policy_authentication() + +// Perform both shim/MOK and platform Secure Boot authentication. This function loads +// the file and performs shim/MOK authentication first simply to avoid double loads +// of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed, +// since kernels are big and can take several seconds to load on some computers and +// filesystems. This also has the effect of returning whatever the platform code is for +// authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something +// else. (This seems to vary between implementations.) +static MSABI EFI_STATUS security_policy_authentication ( const EFI_SECURITY_PROTOCOL *This, UINT32 AuthenticationStatus, const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst ) { - EFI_STATUS status; - EFI_DEVICE_PATH *DevPath - = DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst), - *OrigDevPath = DevPath; - EFI_HANDLE h; - EFI_FILE *f; - VOID *FileBuffer; - UINTN FileSize; - CHAR16* DevPathStr; - - /* Chain original security policy */ - status = refit_call3_wrapper(esfas, This, AuthenticationStatus, DevicePathConst); + EFI_STATUS Status; + EFI_DEVICE_PATH *DevPath, *OrigDevPath; + EFI_HANDLE h; + EFI_FILE *f; + VOID *FileBuffer; + UINTN FileSize; + CHAR16 *DevPathStr; + + if (DevicePathConst == NULL) { + return EFI_INVALID_PARAMETER; + } else { + DevPath = OrigDevPath = DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst); + } - /* if OK avoid checking MOK: It's a bit expensive to - * read the whole file in again (esfas already did this) */ - if (status == EFI_SUCCESS) - goto out; - - status = refit_call3_wrapper(BS->LocateDevicePath, &SIMPLE_FS_PROTOCOL, &DevPath, &h); - if (status != EFI_SUCCESS) + Status = refit_call3_wrapper(BS->LocateDevicePath, &SIMPLE_FS_PROTOCOL, &DevPath, &h); + if (Status != EFI_SUCCESS) goto out; DevPathStr = DevicePathToStr(DevPath); - status = simple_file_open_by_handle(h, DevPathStr, &f, EFI_FILE_MODE_READ); - FreePool(DevPathStr); - if (status != EFI_SUCCESS) + Status = simple_file_open_by_handle(h, DevPathStr, &f, EFI_FILE_MODE_READ); + MyFreePool(DevPathStr); + if (Status != EFI_SUCCESS) goto out; - status = simple_file_read_all(f, &FileSize, &FileBuffer); + Status = simple_file_read_all(f, &FileSize, &FileBuffer); simple_file_close(f); - if (status != EFI_SUCCESS) + if (Status != EFI_SUCCESS) goto out; if (ShimValidate(FileBuffer, FileSize)) { - status = EFI_SUCCESS; + Status = EFI_SUCCESS; } else { - status = EFI_ACCESS_DENIED; + // Try using the platform's native policy.... + Status = uefi_call_wrapper(esfas, 3, This, AuthenticationStatus, DevicePathConst); } FreePool(FileBuffer); out: - FreePool(OrigDevPath); - return status; -} - -#ifdef __MAKEWITH_GNUEFI -/* Nasty: ELF and EFI have different calling conventions. Here is the map for - * calling ELF -> EFI - * - * 1) rdi -> rcx (32 saved) - * 2) rsi -> rdx (32 saved) - * 3) rdx -> r8 ( 32 saved) - * 4) rcx -> r9 (32 saved) - * 5) r8 -> 32(%rsp) (48 saved) - * 6) r9 -> 40(%rsp) (48 saved) - * 7) pad+0(%rsp) -> 48(%rsp) (64 saved) - * 8) pad+8(%rsp) -> 56(%rsp) (64 saved) - * 9) pad+16(%rsp) -> 64(%rsp) (80 saved) - * 10) pad+24(%rsp) -> 72(%rsp) (80 saved) - * 11) pad+32(%rsp) -> 80(%rsp) (96 saved) - - * - * So for a five argument callback, the map is ignore the first two arguments - * and then map (EFI -> ELF) assuming pad = 0. - * - * ARG4 -> ARG1 - * ARG3 -> ARG2 - * ARG5 -> ARG3 - * ARG6 -> ARG4 - * ARG11 -> ARG5 - * - * Calling conventions also differ over volatile and preserved registers in - * MS: RBX, RBP, RDI, RSI, R12, R13, R14, and R15 are considered nonvolatile . - * In ELF: Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling - * function and the called function is required to preserve their values. - * - * This means when accepting a function callback from MS -> ELF, we have to do - * separate preservation on %rdi, %rsi before swizzling the arguments and - * handing off to the ELF function. - */ - -asm ( -".type security2_policy_authentication,@function\n" -"thunk_security2_policy_authentication:\n\t" - "mov 0x28(%rsp), %r10 # ARG5\n\t" - "push %rdi\n\t" - "push %rsi\n\t" - "mov %r10, %rdi\n\t" - "subq $8, %rsp # space for storing stack pad\n\t" - "mov $0x08, %rax\n\t" - "mov $0x10, %r10\n\t" - "and %rsp, %rax\n\t" - "cmovnz %rax, %r11\n\t" - "cmovz %r10, %r11\n\t" - "subq %r11, %rsp\n\t" - "addq $8, %r11\n\t" - "mov %r11, (%rsp)\n\t" -"# five argument swizzle\n\t" - "mov %rdi, %r10\n\t" - "mov %rcx, %rdi\n\t" - "mov %rdx, %rsi\n\t" - "mov %r8, %rdx\n\t" - "mov %r9, %rcx\n\t" - "mov %r10, %r8\n\t" - "callq security2_policy_authentication@PLT\n\t" - "mov (%rsp), %r11\n\t" - "addq %r11, %rsp\n\t" - "pop %rsi\n\t" - "pop %rdi\n\t" - "ret\n" -); - -asm ( -".type security_policy_authentication,@function\n" -"thunk_security_policy_authentication:\n\t" - "push %rdi\n\t" - "push %rsi\n\t" - "subq $8, %rsp # space for storing stack pad\n\t" - "mov $0x08, %rax\n\t" - "mov $0x10, %r10\n\t" - "and %rsp, %rax\n\t" - "cmovnz %rax, %r11\n\t" - "cmovz %r10, %r11\n\t" - "subq %r11, %rsp\n\t" - "addq $8, %r11\n\t" - "mov %r11, (%rsp)\n\t" -"# three argument swizzle\n\t" - "mov %rcx, %rdi\n\t" - "mov %rdx, %rsi\n\t" - "mov %r8, %rdx\n\t" - "callq security_policy_authentication@PLT\n\t" - "mov (%rsp), %r11\n\t" - "addq %r11, %rsp\n\t" - "pop %rsi\n\t" - "pop %rdi\n\t" - "ret\n" -); -#endif + MyFreePool(OrigDevPath); + return Status; +} // EFI_STATUS security_policy_authentication() EFI_STATUS security_policy_install(void) @@ -286,19 +168,11 @@ security_policy_install(void) if (security2_protocol) { es2fa = security2_protocol->FileAuthentication; -#ifdef __MAKEWITH_GNUEFI - security2_protocol->FileAuthentication = thunk_security2_policy_authentication; -#else security2_protocol->FileAuthentication = security2_policy_authentication; -#endif } esfas = security_protocol->FileAuthenticationState; -#ifdef __MAKEWITH_GNUEFI - security_protocol->FileAuthenticationState = thunk_security_policy_authentication; -#else security_protocol->FileAuthenticationState = security_policy_authentication; -#endif return EFI_SUCCESS; } @@ -310,9 +184,7 @@ security_policy_uninstall(void) if (esfas) { EFI_SECURITY_PROTOCOL *security_protocol; - status = uefi_call_wrapper(BS->LocateProtocol, 3, - &SECURITY_PROTOCOL_GUID, NULL, - (VOID**) &security_protocol); + status = uefi_call_wrapper(BS->LocateProtocol, 3, &SECURITY_PROTOCOL_GUID, NULL, (VOID**) &security_protocol); if (status != EFI_SUCCESS) return status; @@ -327,9 +199,7 @@ security_policy_uninstall(void) if (es2fa) { EFI_SECURITY2_PROTOCOL *security2_protocol; - status = uefi_call_wrapper(BS->LocateProtocol, 3, - &SECURITY2_PROTOCOL_GUID, NULL, - (VOID**) &security2_protocol); + status = uefi_call_wrapper(BS->LocateProtocol, 3, &SECURITY2_PROTOCOL_GUID, NULL, (VOID**) &security2_protocol); if (status != EFI_SUCCESS) return status; @@ -340,10 +210,3 @@ security_policy_uninstall(void) return EFI_SUCCESS; } - -void -security_protocol_set_hashes(unsigned char *esl, int len) -{ - security_policy_esl = esl; - security_policy_esl_len = len; -}