Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include <linux/kernel.h>
0004 #include <linux/sched.h>
0005 #include <linux/cred.h>
0006 #include <linux/dmi.h>
0007 #include <linux/err.h>
0008 #include <linux/efi.h>
0009 #include <linux/slab.h>
0010 #include <linux/ima.h>
0011 #include <keys/asymmetric-type.h>
0012 #include <keys/system_keyring.h>
0013 #include "../integrity.h"
0014 #include "keyring_handler.h"
0015 
0016 /*
0017  * On T2 Macs reading the db and dbx efi variables to load UEFI Secure Boot
0018  * certificates causes occurrence of a page fault in Apple's firmware and
0019  * a crash disabling EFI runtime services. The following quirk skips reading
0020  * these variables.
0021  */
0022 static const struct dmi_system_id uefi_skip_cert[] = {
0023     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,1") },
0024     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,2") },
0025     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,3") },
0026     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,4") },
0027     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,1") },
0028     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,2") },
0029     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,3") },
0030     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,4") },
0031     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,1") },
0032     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,2") },
0033     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir9,1") },
0034     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacMini8,1") },
0035     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacPro7,1") },
0036     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,1") },
0037     { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,2") },
0038     { }
0039 };
0040 
0041 /*
0042  * Look to see if a UEFI variable called MokIgnoreDB exists and return true if
0043  * it does.
0044  *
0045  * This UEFI variable is set by the shim if a user tells the shim to not use
0046  * the certs/hashes in the UEFI db variable for verification purposes.  If it
0047  * is set, we should ignore the db variable also and the true return indicates
0048  * this.
0049  */
0050 static __init bool uefi_check_ignore_db(void)
0051 {
0052     efi_status_t status;
0053     unsigned int db = 0;
0054     unsigned long size = sizeof(db);
0055     efi_guid_t guid = EFI_SHIM_LOCK_GUID;
0056 
0057     status = efi.get_variable(L"MokIgnoreDB", &guid, NULL, &size, &db);
0058     return status == EFI_SUCCESS;
0059 }
0060 
0061 /*
0062  * Get a certificate list blob from the named EFI variable.
0063  */
0064 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
0065                   unsigned long *size, efi_status_t *status)
0066 {
0067     unsigned long lsize = 4;
0068     unsigned long tmpdb[4];
0069     void *db;
0070 
0071     *status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
0072     if (*status == EFI_NOT_FOUND)
0073         return NULL;
0074 
0075     if (*status != EFI_BUFFER_TOO_SMALL) {
0076         pr_err("Couldn't get size: 0x%lx\n", *status);
0077         return NULL;
0078     }
0079 
0080     db = kmalloc(lsize, GFP_KERNEL);
0081     if (!db)
0082         return NULL;
0083 
0084     *status = efi.get_variable(name, guid, NULL, &lsize, db);
0085     if (*status != EFI_SUCCESS) {
0086         kfree(db);
0087         pr_err("Error reading db var: 0x%lx\n", *status);
0088         return NULL;
0089     }
0090 
0091     *size = lsize;
0092     return db;
0093 }
0094 
0095 /*
0096  * load_moklist_certs() - Load MokList certs
0097  *
0098  * Load the certs contained in the UEFI MokListRT database into the
0099  * platform trusted keyring.
0100  *
0101  * This routine checks the EFI MOK config table first. If and only if
0102  * that fails, this routine uses the MokListRT ordinary UEFI variable.
0103  *
0104  * Return:  Status
0105  */
0106 static int __init load_moklist_certs(void)
0107 {
0108     struct efi_mokvar_table_entry *mokvar_entry;
0109     efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
0110     void *mok;
0111     unsigned long moksize;
0112     efi_status_t status;
0113     int rc;
0114 
0115     /* First try to load certs from the EFI MOKvar config table.
0116      * It's not an error if the MOKvar config table doesn't exist
0117      * or the MokListRT entry is not found in it.
0118      */
0119     mokvar_entry = efi_mokvar_entry_find("MokListRT");
0120     if (mokvar_entry) {
0121         rc = parse_efi_signature_list("UEFI:MokListRT (MOKvar table)",
0122                           mokvar_entry->data,
0123                           mokvar_entry->data_size,
0124                           get_handler_for_mok);
0125         /* All done if that worked. */
0126         if (!rc)
0127             return rc;
0128 
0129         pr_err("Couldn't parse MokListRT signatures from EFI MOKvar config table: %d\n",
0130                rc);
0131     }
0132 
0133     /* Get MokListRT. It might not exist, so it isn't an error
0134      * if we can't get it.
0135      */
0136     mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status);
0137     if (mok) {
0138         rc = parse_efi_signature_list("UEFI:MokListRT",
0139                           mok, moksize, get_handler_for_mok);
0140         kfree(mok);
0141         if (rc)
0142             pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
0143         return rc;
0144     }
0145     if (status == EFI_NOT_FOUND)
0146         pr_debug("MokListRT variable wasn't found\n");
0147     else
0148         pr_info("Couldn't get UEFI MokListRT\n");
0149     return 0;
0150 }
0151 
0152 /*
0153  * load_uefi_certs() - Load certs from UEFI sources
0154  *
0155  * Load the certs contained in the UEFI databases into the platform trusted
0156  * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist
0157  * keyring.
0158  */
0159 static int __init load_uefi_certs(void)
0160 {
0161     efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
0162     efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
0163     void *db = NULL, *dbx = NULL, *mokx = NULL;
0164     unsigned long dbsize = 0, dbxsize = 0, mokxsize = 0;
0165     efi_status_t status;
0166     int rc = 0;
0167     const struct dmi_system_id *dmi_id;
0168 
0169     dmi_id = dmi_first_match(uefi_skip_cert);
0170     if (dmi_id) {
0171         pr_err("Reading UEFI Secure Boot Certs is not supported on T2 Macs.\n");
0172         return false;
0173     }
0174 
0175     if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
0176         return false;
0177 
0178     /* Get db and dbx.  They might not exist, so it isn't an error
0179      * if we can't get them.
0180      */
0181     if (!uefi_check_ignore_db()) {
0182         db = get_cert_list(L"db", &secure_var, &dbsize, &status);
0183         if (!db) {
0184             if (status == EFI_NOT_FOUND)
0185                 pr_debug("MODSIGN: db variable wasn't found\n");
0186             else
0187                 pr_err("MODSIGN: Couldn't get UEFI db list\n");
0188         } else {
0189             rc = parse_efi_signature_list("UEFI:db",
0190                     db, dbsize, get_handler_for_db);
0191             if (rc)
0192                 pr_err("Couldn't parse db signatures: %d\n",
0193                        rc);
0194             kfree(db);
0195         }
0196     }
0197 
0198     dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status);
0199     if (!dbx) {
0200         if (status == EFI_NOT_FOUND)
0201             pr_debug("dbx variable wasn't found\n");
0202         else
0203             pr_info("Couldn't get UEFI dbx list\n");
0204     } else {
0205         rc = parse_efi_signature_list("UEFI:dbx",
0206                           dbx, dbxsize,
0207                           get_handler_for_dbx);
0208         if (rc)
0209             pr_err("Couldn't parse dbx signatures: %d\n", rc);
0210         kfree(dbx);
0211     }
0212 
0213     /* the MOK/MOKx can not be trusted when secure boot is disabled */
0214     if (!arch_ima_get_secureboot())
0215         return 0;
0216 
0217     mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status);
0218     if (!mokx) {
0219         if (status == EFI_NOT_FOUND)
0220             pr_debug("mokx variable wasn't found\n");
0221         else
0222             pr_info("Couldn't get mokx list\n");
0223     } else {
0224         rc = parse_efi_signature_list("UEFI:MokListXRT",
0225                           mokx, mokxsize,
0226                           get_handler_for_dbx);
0227         if (rc)
0228             pr_err("Couldn't parse mokx signatures %d\n", rc);
0229         kfree(mokx);
0230     }
0231 
0232     /* Load the MokListRT certs */
0233     rc = load_moklist_certs();
0234 
0235     return rc;
0236 }
0237 late_initcall(load_uefi_certs);