load_uefi.c (6818B)
1// SPDX-License-Identifier: GPL-2.0 2 3#include <linux/kernel.h> 4#include <linux/sched.h> 5#include <linux/cred.h> 6#include <linux/dmi.h> 7#include <linux/err.h> 8#include <linux/efi.h> 9#include <linux/slab.h> 10#include <linux/ima.h> 11#include <keys/asymmetric-type.h> 12#include <keys/system_keyring.h> 13#include "../integrity.h" 14#include "keyring_handler.h" 15 16/* 17 * On T2 Macs reading the db and dbx efi variables to load UEFI Secure Boot 18 * certificates causes occurrence of a page fault in Apple's firmware and 19 * a crash disabling EFI runtime services. The following quirk skips reading 20 * these variables. 21 */ 22static const struct dmi_system_id uefi_skip_cert[] = { 23 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,1") }, 24 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,2") }, 25 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,3") }, 26 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,4") }, 27 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,1") }, 28 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,2") }, 29 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,3") }, 30 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,4") }, 31 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,1") }, 32 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,2") }, 33 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir9,1") }, 34 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacMini8,1") }, 35 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacPro7,1") }, 36 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,1") }, 37 { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,2") }, 38 { } 39}; 40 41/* 42 * Look to see if a UEFI variable called MokIgnoreDB exists and return true if 43 * it does. 44 * 45 * This UEFI variable is set by the shim if a user tells the shim to not use 46 * the certs/hashes in the UEFI db variable for verification purposes. If it 47 * is set, we should ignore the db variable also and the true return indicates 48 * this. 49 */ 50static __init bool uefi_check_ignore_db(void) 51{ 52 efi_status_t status; 53 unsigned int db = 0; 54 unsigned long size = sizeof(db); 55 efi_guid_t guid = EFI_SHIM_LOCK_GUID; 56 57 status = efi.get_variable(L"MokIgnoreDB", &guid, NULL, &size, &db); 58 return status == EFI_SUCCESS; 59} 60 61/* 62 * Get a certificate list blob from the named EFI variable. 63 */ 64static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, 65 unsigned long *size, efi_status_t *status) 66{ 67 unsigned long lsize = 4; 68 unsigned long tmpdb[4]; 69 void *db; 70 71 *status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); 72 if (*status == EFI_NOT_FOUND) 73 return NULL; 74 75 if (*status != EFI_BUFFER_TOO_SMALL) { 76 pr_err("Couldn't get size: 0x%lx\n", *status); 77 return NULL; 78 } 79 80 db = kmalloc(lsize, GFP_KERNEL); 81 if (!db) 82 return NULL; 83 84 *status = efi.get_variable(name, guid, NULL, &lsize, db); 85 if (*status != EFI_SUCCESS) { 86 kfree(db); 87 pr_err("Error reading db var: 0x%lx\n", *status); 88 return NULL; 89 } 90 91 *size = lsize; 92 return db; 93} 94 95/* 96 * load_moklist_certs() - Load MokList certs 97 * 98 * Load the certs contained in the UEFI MokListRT database into the 99 * platform trusted keyring. 100 * 101 * This routine checks the EFI MOK config table first. If and only if 102 * that fails, this routine uses the MokListRT ordinary UEFI variable. 103 * 104 * Return: Status 105 */ 106static int __init load_moklist_certs(void) 107{ 108 struct efi_mokvar_table_entry *mokvar_entry; 109 efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; 110 void *mok; 111 unsigned long moksize; 112 efi_status_t status; 113 int rc; 114 115 /* First try to load certs from the EFI MOKvar config table. 116 * It's not an error if the MOKvar config table doesn't exist 117 * or the MokListRT entry is not found in it. 118 */ 119 mokvar_entry = efi_mokvar_entry_find("MokListRT"); 120 if (mokvar_entry) { 121 rc = parse_efi_signature_list("UEFI:MokListRT (MOKvar table)", 122 mokvar_entry->data, 123 mokvar_entry->data_size, 124 get_handler_for_mok); 125 /* All done if that worked. */ 126 if (!rc) 127 return rc; 128 129 pr_err("Couldn't parse MokListRT signatures from EFI MOKvar config table: %d\n", 130 rc); 131 } 132 133 /* Get MokListRT. It might not exist, so it isn't an error 134 * if we can't get it. 135 */ 136 mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status); 137 if (mok) { 138 rc = parse_efi_signature_list("UEFI:MokListRT", 139 mok, moksize, get_handler_for_mok); 140 kfree(mok); 141 if (rc) 142 pr_err("Couldn't parse MokListRT signatures: %d\n", rc); 143 return rc; 144 } 145 if (status == EFI_NOT_FOUND) 146 pr_debug("MokListRT variable wasn't found\n"); 147 else 148 pr_info("Couldn't get UEFI MokListRT\n"); 149 return 0; 150} 151 152/* 153 * load_uefi_certs() - Load certs from UEFI sources 154 * 155 * Load the certs contained in the UEFI databases into the platform trusted 156 * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist 157 * keyring. 158 */ 159static int __init load_uefi_certs(void) 160{ 161 efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; 162 efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; 163 void *db = NULL, *dbx = NULL, *mokx = NULL; 164 unsigned long dbsize = 0, dbxsize = 0, mokxsize = 0; 165 efi_status_t status; 166 int rc = 0; 167 const struct dmi_system_id *dmi_id; 168 169 dmi_id = dmi_first_match(uefi_skip_cert); 170 if (dmi_id) { 171 pr_err("Reading UEFI Secure Boot Certs is not supported on T2 Macs.\n"); 172 return false; 173 } 174 175 if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) 176 return false; 177 178 /* Get db and dbx. They might not exist, so it isn't an error 179 * if we can't get them. 180 */ 181 if (!uefi_check_ignore_db()) { 182 db = get_cert_list(L"db", &secure_var, &dbsize, &status); 183 if (!db) { 184 if (status == EFI_NOT_FOUND) 185 pr_debug("MODSIGN: db variable wasn't found\n"); 186 else 187 pr_err("MODSIGN: Couldn't get UEFI db list\n"); 188 } else { 189 rc = parse_efi_signature_list("UEFI:db", 190 db, dbsize, get_handler_for_db); 191 if (rc) 192 pr_err("Couldn't parse db signatures: %d\n", 193 rc); 194 kfree(db); 195 } 196 } 197 198 dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status); 199 if (!dbx) { 200 if (status == EFI_NOT_FOUND) 201 pr_debug("dbx variable wasn't found\n"); 202 else 203 pr_info("Couldn't get UEFI dbx list\n"); 204 } else { 205 rc = parse_efi_signature_list("UEFI:dbx", 206 dbx, dbxsize, 207 get_handler_for_dbx); 208 if (rc) 209 pr_err("Couldn't parse dbx signatures: %d\n", rc); 210 kfree(dbx); 211 } 212 213 /* the MOK/MOKx can not be trusted when secure boot is disabled */ 214 if (!arch_ima_get_secureboot()) 215 return 0; 216 217 mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status); 218 if (!mokx) { 219 if (status == EFI_NOT_FOUND) 220 pr_debug("mokx variable wasn't found\n"); 221 else 222 pr_info("Couldn't get mokx list\n"); 223 } else { 224 rc = parse_efi_signature_list("UEFI:MokListXRT", 225 mokx, mokxsize, 226 get_handler_for_dbx); 227 if (rc) 228 pr_err("Couldn't parse mokx signatures %d\n", rc); 229 kfree(mokx); 230 } 231 232 /* Load the MokListRT certs */ 233 rc = load_moklist_certs(); 234 235 return rc; 236} 237late_initcall(load_uefi_certs);