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)
39 {
40 	efi_status_t status;
41 	unsigned long lsize = 4;
42 	unsigned long tmpdb[4];
43 	void *db;
44 
45 	status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
46 	if (status != EFI_BUFFER_TOO_SMALL) {
47 		pr_err("Couldn't get size: 0x%lx\n", status);
48 		return NULL;
49 	}
50 
51 	db = kmalloc(lsize, GFP_KERNEL);
52 	if (!db)
53 		return NULL;
54 
55 	status = efi.get_variable(name, guid, NULL, &lsize, db);
56 	if (status != EFI_SUCCESS) {
57 		kfree(db);
58 		pr_err("Error reading db var: 0x%lx\n", status);
59 		return NULL;
60 	}
61 
62 	*size = lsize;
63 	return db;
64 }
65 
66 /*
67  * Load the certs contained in the UEFI databases into the platform trusted
68  * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist
69  * keyring.
70  */
71 static int __init load_uefi_certs(void)
72 {
73 	efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
74 	efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
75 	void *db = NULL, *dbx = NULL, *mok = NULL;
76 	unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
77 	int rc = 0;
78 
79 	if (!efi.get_variable)
80 		return false;
81 
82 	/* Get db, MokListRT, and dbx.  They might not exist, so it isn't
83 	 * an error if we can't get them.
84 	 */
85 	if (!uefi_check_ignore_db()) {
86 		db = get_cert_list(L"db", &secure_var, &dbsize);
87 		if (!db) {
88 			pr_err("MODSIGN: Couldn't get UEFI db list\n");
89 		} else {
90 			rc = parse_efi_signature_list("UEFI:db",
91 					db, dbsize, get_handler_for_db);
92 			if (rc)
93 				pr_err("Couldn't parse db signatures: %d\n",
94 				       rc);
95 			kfree(db);
96 		}
97 	}
98 
99 	mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
100 	if (!mok) {
101 		pr_info("Couldn't get UEFI MokListRT\n");
102 	} else {
103 		rc = parse_efi_signature_list("UEFI:MokListRT",
104 					      mok, moksize, get_handler_for_db);
105 		if (rc)
106 			pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
107 		kfree(mok);
108 	}
109 
110 	dbx = get_cert_list(L"dbx", &secure_var, &dbxsize);
111 	if (!dbx) {
112 		pr_info("Couldn't get UEFI dbx list\n");
113 	} else {
114 		rc = parse_efi_signature_list("UEFI:dbx",
115 					      dbx, dbxsize,
116 					      get_handler_for_dbx);
117 		if (rc)
118 			pr_err("Couldn't parse dbx signatures: %d\n", rc);
119 		kfree(dbx);
120 	}
121 
122 	return rc;
123 }
124 late_initcall(load_uefi_certs);
125