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/err.h> 7 #include <linux/efi.h> 8 #include <linux/slab.h> 9 #include <keys/asymmetric-type.h> 10 #include <keys/system_keyring.h> 11 #include "../integrity.h" 12 #include "keyring_handler.h" 13 14 /* 15 * Look to see if a UEFI variable called MokIgnoreDB exists and return true if 16 * it does. 17 * 18 * This UEFI variable is set by the shim if a user tells the shim to not use 19 * the certs/hashes in the UEFI db variable for verification purposes. If it 20 * is set, we should ignore the db variable also and the true return indicates 21 * this. 22 */ 23 static __init bool uefi_check_ignore_db(void) 24 { 25 efi_status_t status; 26 unsigned int db = 0; 27 unsigned long size = sizeof(db); 28 efi_guid_t guid = EFI_SHIM_LOCK_GUID; 29 30 status = efi.get_variable(L"MokIgnoreDB", &guid, NULL, &size, &db); 31 return status == EFI_SUCCESS; 32 } 33 34 /* 35 * Get a certificate list blob from the named EFI variable. 36 */ 37 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, 38 unsigned long *size, efi_status_t *status) 39 { 40 unsigned long lsize = 4; 41 unsigned long tmpdb[4]; 42 void *db; 43 44 *status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); 45 if (*status == EFI_NOT_FOUND) 46 return NULL; 47 48 if (*status != EFI_BUFFER_TOO_SMALL) { 49 pr_err("Couldn't get size: 0x%lx\n", *status); 50 return NULL; 51 } 52 53 db = kmalloc(lsize, GFP_KERNEL); 54 if (!db) 55 return NULL; 56 57 *status = efi.get_variable(name, guid, NULL, &lsize, db); 58 if (*status != EFI_SUCCESS) { 59 kfree(db); 60 pr_err("Error reading db var: 0x%lx\n", *status); 61 return NULL; 62 } 63 64 *size = lsize; 65 return db; 66 } 67 68 /* 69 * load_moklist_certs() - Load MokList certs 70 * 71 * Load the certs contained in the UEFI MokListRT database into the 72 * platform trusted keyring. 73 * 74 * This routine checks the EFI MOK config table first. If and only if 75 * that fails, this routine uses the MokListRT ordinary UEFI variable. 76 * 77 * Return: Status 78 */ 79 static int __init load_moklist_certs(void) 80 { 81 struct efi_mokvar_table_entry *mokvar_entry; 82 efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; 83 void *mok; 84 unsigned long moksize; 85 efi_status_t status; 86 int rc; 87 88 /* First try to load certs from the EFI MOKvar config table. 89 * It's not an error if the MOKvar config table doesn't exist 90 * or the MokListRT entry is not found in it. 91 */ 92 mokvar_entry = efi_mokvar_entry_find("MokListRT"); 93 if (mokvar_entry) { 94 rc = parse_efi_signature_list("UEFI:MokListRT (MOKvar table)", 95 mokvar_entry->data, 96 mokvar_entry->data_size, 97 get_handler_for_db); 98 /* All done if that worked. */ 99 if (!rc) 100 return rc; 101 102 pr_err("Couldn't parse MokListRT signatures from EFI MOKvar config table: %d\n", 103 rc); 104 } 105 106 /* Get MokListRT. It might not exist, so it isn't an error 107 * if we can't get it. 108 */ 109 mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status); 110 if (mok) { 111 rc = parse_efi_signature_list("UEFI:MokListRT", 112 mok, moksize, get_handler_for_db); 113 kfree(mok); 114 if (rc) 115 pr_err("Couldn't parse MokListRT signatures: %d\n", rc); 116 return rc; 117 } 118 if (status == EFI_NOT_FOUND) 119 pr_debug("MokListRT variable wasn't found\n"); 120 else 121 pr_info("Couldn't get UEFI MokListRT\n"); 122 return 0; 123 } 124 125 /* 126 * load_uefi_certs() - Load certs from UEFI sources 127 * 128 * Load the certs contained in the UEFI databases into the platform trusted 129 * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist 130 * keyring. 131 */ 132 static int __init load_uefi_certs(void) 133 { 134 efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; 135 efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; 136 void *db = NULL, *dbx = NULL, *mokx = NULL; 137 unsigned long dbsize = 0, dbxsize = 0, mokxsize = 0; 138 efi_status_t status; 139 int rc = 0; 140 141 if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) 142 return false; 143 144 /* Get db and dbx. They might not exist, so it isn't an error 145 * if we can't get them. 146 */ 147 if (!uefi_check_ignore_db()) { 148 db = get_cert_list(L"db", &secure_var, &dbsize, &status); 149 if (!db) { 150 if (status == EFI_NOT_FOUND) 151 pr_debug("MODSIGN: db variable wasn't found\n"); 152 else 153 pr_err("MODSIGN: Couldn't get UEFI db list\n"); 154 } else { 155 rc = parse_efi_signature_list("UEFI:db", 156 db, dbsize, get_handler_for_db); 157 if (rc) 158 pr_err("Couldn't parse db signatures: %d\n", 159 rc); 160 kfree(db); 161 } 162 } 163 164 dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status); 165 if (!dbx) { 166 if (status == EFI_NOT_FOUND) 167 pr_debug("dbx variable wasn't found\n"); 168 else 169 pr_info("Couldn't get UEFI dbx list\n"); 170 } else { 171 rc = parse_efi_signature_list("UEFI:dbx", 172 dbx, dbxsize, 173 get_handler_for_dbx); 174 if (rc) 175 pr_err("Couldn't parse dbx signatures: %d\n", rc); 176 kfree(dbx); 177 } 178 179 mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status); 180 if (!mokx) { 181 if (status == EFI_NOT_FOUND) 182 pr_debug("mokx variable wasn't found\n"); 183 else 184 pr_info("Couldn't get mokx list\n"); 185 } else { 186 rc = parse_efi_signature_list("UEFI:MokListXRT", 187 mokx, mokxsize, 188 get_handler_for_dbx); 189 if (rc) 190 pr_err("Couldn't parse mokx signatures %d\n", rc); 191 kfree(mokx); 192 } 193 194 /* Load the MokListRT certs */ 195 rc = load_moklist_certs(); 196 197 return rc; 198 } 199 late_initcall(load_uefi_certs); 200