]> code.delx.au - refind/blob - mok/mok.c
3948b08af03d6482f70b6855c4a86ff5a5a56fe5
[refind] / mok / mok.c
1 /* mok/mok.c
2 *
3 * Based mostly on shim.c by Matthew J. Garrett/Red Hat (see below
4 * copyright notice).
5 *
6 * Code to perform Secure Boot verification of boot loader programs
7 * using the Shim program and its Machine Owner Keys (MOKs), to
8 * supplement standard Secure Boot checks performed by the firmware.
9 *
10 */
11
12 /*
13 * shim - trivial UEFI first-stage bootloader
14 *
15 * Copyright 2012 Red Hat, Inc <mjg@redhat.com>
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 *
21 * Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 *
24 * Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the
27 * distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
38 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
40 * OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 * Significant portions of this code are derived from Tianocore
43 * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel
44 * Corporation.
45 */
46
47 #include "global.h"
48 #include "mok.h"
49 #include "../include/refit_call_wrapper.h"
50
51 static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, UINTN *size, VOID **buffer)
52 {
53 EFI_STATUS efi_status;
54 char allocate = !(*size);
55
56 efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, buffer);
57
58 if (efi_status != EFI_BUFFER_TOO_SMALL || !allocate) {
59 return efi_status;
60 }
61
62 *buffer = AllocatePool(*size);
63
64 if (!*buffer) {
65 Print(L"Unable to allocate variable buffer\n");
66 return EFI_OUT_OF_RESOURCES;
67 }
68
69 efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, *buffer);
70
71 return efi_status;
72 } // get_variable()
73
74 /*
75 * Check whether we're in Secure Boot and user mode
76 */
77 BOOLEAN secure_mode (VOID)
78 {
79 EFI_STATUS status;
80 EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
81 UINTN charsize = sizeof(char);
82 UINT8 sb, setupmode;
83 UINT32 attributes;
84
85 status = get_variable(L"SecureBoot", global_var, &attributes, &charsize, (VOID *)&sb);
86
87 /* FIXME - more paranoia here? */
88 if (status != EFI_SUCCESS || sb != 1) {
89 return FALSE;
90 }
91
92 status = get_variable(L"SetupMode", global_var, &attributes, &charsize, (VOID *)&setupmode);
93
94 if (status == EFI_SUCCESS && setupmode == 1) {
95 return FALSE;
96 }
97
98 return TRUE;
99 } // secure_mode()
100
101 // Returns TRUE if the shim program is available to verify binaries,
102 // FALSE if not
103 BOOLEAN ShimLoaded(void) {
104 SHIM_LOCK *shim_lock;
105 EFI_GUID ShimLockGuid = SHIM_LOCK_GUID;
106
107 return (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS);
108 } // ShimLoaded()
109
110 // The following is based on the grub_linuxefi_secure_validate() function in Fedora's
111 // version of GRUB 2.
112 // Returns TRUE if the specified data is validated by Shim's MOK, FALSE otherwise
113 BOOLEAN ShimValidate (VOID *data, UINT32 size)
114 {
115 SHIM_LOCK *shim_lock;
116 EFI_GUID ShimLockGuid = SHIM_LOCK_GUID;
117
118 if ((data != NULL) && (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS)) {
119 if (!shim_lock)
120 return FALSE;
121
122 if (shim_lock->shim_verify(data, size) == EFI_SUCCESS)
123 return TRUE;
124 }
125
126 return FALSE;
127 } // BOOLEAN ShimValidate()