Path: blob/master/security/integrity/platform_certs/load_uefi.c
26424 views
// SPDX-License-Identifier: GPL-2.012#include <linux/kernel.h>3#include <linux/sched.h>4#include <linux/cred.h>5#include <linux/dmi.h>6#include <linux/err.h>7#include <linux/efi.h>8#include <linux/slab.h>9#include <linux/ima.h>10#include <keys/asymmetric-type.h>11#include <keys/system_keyring.h>12#include "../integrity.h"13#include "keyring_handler.h"1415/*16* On T2 Macs reading the db and dbx efi variables to load UEFI Secure Boot17* certificates causes occurrence of a page fault in Apple's firmware and18* a crash disabling EFI runtime services. The following quirk skips reading19* these variables.20*/21static const struct dmi_system_id uefi_skip_cert[] = {22{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,1") },23{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,2") },24{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,3") },25{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,4") },26{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,1") },27{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,2") },28{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,3") },29{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,4") },30{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,1") },31{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,2") },32{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir9,1") },33{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "Macmini8,1") },34{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacPro7,1") },35{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,1") },36{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,2") },37{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMacPro1,1") },38{ }39};4041/*42* Look to see if a UEFI variable called MokIgnoreDB exists and return true if43* it does.44*45* This UEFI variable is set by the shim if a user tells the shim to not use46* the certs/hashes in the UEFI db variable for verification purposes. If it47* is set, we should ignore the db variable also and the true return indicates48* this.49*/50static __init bool uefi_check_ignore_db(void)51{52efi_status_t status;53unsigned int db = 0;54unsigned long size = sizeof(db);55efi_guid_t guid = EFI_SHIM_LOCK_GUID;5657status = efi.get_variable(L"MokIgnoreDB", &guid, NULL, &size, &db);58return status == EFI_SUCCESS;59}6061/*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,65unsigned long *size, efi_status_t *status)66{67unsigned long lsize = 4;68unsigned long tmpdb[4];69void *db;7071*status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);72if (*status == EFI_NOT_FOUND)73return NULL;7475if (*status != EFI_BUFFER_TOO_SMALL) {76pr_err("Couldn't get size: 0x%lx\n", *status);77return NULL;78}7980db = kmalloc(lsize, GFP_KERNEL);81if (!db)82return NULL;8384*status = efi.get_variable(name, guid, NULL, &lsize, db);85if (*status != EFI_SUCCESS) {86kfree(db);87pr_err("Error reading db var: 0x%lx\n", *status);88return NULL;89}9091*size = lsize;92return db;93}9495/*96* load_moklist_certs() - Load MokList certs97*98* Load the certs contained in the UEFI MokListRT database into the99* platform trusted keyring.100*101* This routine checks the EFI MOK config table first. If and only if102* that fails, this routine uses the MokListRT ordinary UEFI variable.103*104* Return: Status105*/106static int __init load_moklist_certs(void)107{108struct efi_mokvar_table_entry *mokvar_entry;109efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;110void *mok;111unsigned long moksize;112efi_status_t status;113int rc;114115/* First try to load certs from the EFI MOKvar config table.116* It's not an error if the MOKvar config table doesn't exist117* or the MokListRT entry is not found in it.118*/119mokvar_entry = efi_mokvar_entry_find("MokListRT");120if (mokvar_entry) {121rc = parse_efi_signature_list("UEFI:MokListRT (MOKvar table)",122mokvar_entry->data,123mokvar_entry->data_size,124get_handler_for_mok);125/* All done if that worked. */126if (!rc)127return rc;128129pr_err("Couldn't parse MokListRT signatures from EFI MOKvar config table: %d\n",130rc);131}132133/* Get MokListRT. It might not exist, so it isn't an error134* if we can't get it.135*/136mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status);137if (mok) {138rc = parse_efi_signature_list("UEFI:MokListRT",139mok, moksize, get_handler_for_mok);140kfree(mok);141if (rc)142pr_err("Couldn't parse MokListRT signatures: %d\n", rc);143return rc;144}145if (status == EFI_NOT_FOUND)146pr_debug("MokListRT variable wasn't found\n");147else148pr_info("Couldn't get UEFI MokListRT\n");149return 0;150}151152/*153* load_uefi_certs() - Load certs from UEFI sources154*155* Load the certs contained in the UEFI databases into the platform trusted156* keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist157* keyring.158*/159static int __init load_uefi_certs(void)160{161efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;162efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;163void *db = NULL, *dbx = NULL, *mokx = NULL;164unsigned long dbsize = 0, dbxsize = 0, mokxsize = 0;165efi_status_t status;166int rc = 0;167const struct dmi_system_id *dmi_id;168169dmi_id = dmi_first_match(uefi_skip_cert);170if (dmi_id) {171pr_err("Reading UEFI Secure Boot Certs is not supported on T2 Macs.\n");172return false;173}174175if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))176return false;177178/* Get db and dbx. They might not exist, so it isn't an error179* if we can't get them.180*/181if (!uefi_check_ignore_db()) {182db = get_cert_list(L"db", &secure_var, &dbsize, &status);183if (!db) {184if (status == EFI_NOT_FOUND)185pr_debug("MODSIGN: db variable wasn't found\n");186else187pr_err("MODSIGN: Couldn't get UEFI db list\n");188} else {189rc = parse_efi_signature_list("UEFI:db",190db, dbsize, get_handler_for_db);191if (rc)192pr_err("Couldn't parse db signatures: %d\n",193rc);194kfree(db);195}196}197198dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status);199if (!dbx) {200if (status == EFI_NOT_FOUND)201pr_debug("dbx variable wasn't found\n");202else203pr_info("Couldn't get UEFI dbx list\n");204} else {205rc = parse_efi_signature_list("UEFI:dbx",206dbx, dbxsize,207get_handler_for_dbx);208if (rc)209pr_err("Couldn't parse dbx signatures: %d\n", rc);210kfree(dbx);211}212213/* the MOK/MOKx can not be trusted when secure boot is disabled */214if (!arch_ima_get_secureboot())215return 0;216217mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status);218if (!mokx) {219if (status == EFI_NOT_FOUND)220pr_debug("mokx variable wasn't found\n");221else222pr_info("Couldn't get mokx list\n");223} else {224rc = parse_efi_signature_list("UEFI:MokListXRT",225mokx, mokxsize,226get_handler_for_dbx);227if (rc)228pr_err("Couldn't parse mokx signatures %d\n", rc);229kfree(mokx);230}231232/* Load the MokListRT certs */233rc = load_moklist_certs();234235return rc;236}237late_initcall(load_uefi_certs);238239240