]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - certs/load_uefi.c
UBUNTU: SAUCE: (efi-lockdown) MODSIGN: Import certificates from UEFI Secure Boot
[mirror_ubuntu-bionic-kernel.git] / certs / load_uefi.c
1 #include <linux/kernel.h>
2 #include <linux/sched.h>
3 #include <linux/cred.h>
4 #include <linux/err.h>
5 #include <linux/efi.h>
6 #include <linux/slab.h>
7 #include <keys/asymmetric-type.h>
8 #include <keys/system_keyring.h>
9 #include "internal.h"
10
11 static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID;
12 static __initdata efi_guid_t efi_cert_x509_sha256_guid = EFI_CERT_X509_SHA256_GUID;
13 static __initdata efi_guid_t efi_cert_sha256_guid = EFI_CERT_SHA256_GUID;
14
15 /*
16 * Get a certificate list blob from the named EFI variable.
17 */
18 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
19 unsigned long *size)
20 {
21 efi_status_t status;
22 unsigned long lsize = 4;
23 unsigned long tmpdb[4];
24 void *db;
25
26 status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
27 if (status != EFI_BUFFER_TOO_SMALL) {
28 pr_err("Couldn't get size: 0x%lx\n", status);
29 return NULL;
30 }
31
32 db = kmalloc(lsize, GFP_KERNEL);
33 if (!db) {
34 pr_err("Couldn't allocate memory for uefi cert list\n");
35 return NULL;
36 }
37
38 status = efi.get_variable(name, guid, NULL, &lsize, db);
39 if (status != EFI_SUCCESS) {
40 kfree(db);
41 pr_err("Error reading db var: 0x%lx\n", status);
42 return NULL;
43 }
44
45 *size = lsize;
46 return db;
47 }
48
49 /*
50 * Blacklist an X509 TBS hash.
51 */
52 static __init void uefi_blacklist_x509_tbs(const char *source,
53 const void *data, size_t len)
54 {
55 char *hash, *p;
56
57 hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
58 if (!hash)
59 return;
60 p = memcpy(hash, "tbs:", 4);
61 p += 4;
62 bin2hex(p, data, len);
63 p += len * 2;
64 *p = 0;
65
66 mark_hash_blacklisted(hash);
67 kfree(hash);
68 }
69
70 /*
71 * Blacklist the hash of an executable.
72 */
73 static __init void uefi_blacklist_binary(const char *source,
74 const void *data, size_t len)
75 {
76 char *hash, *p;
77
78 hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
79 if (!hash)
80 return;
81 p = memcpy(hash, "bin:", 4);
82 p += 4;
83 bin2hex(p, data, len);
84 p += len * 2;
85 *p = 0;
86
87 mark_hash_blacklisted(hash);
88 kfree(hash);
89 }
90
91 /*
92 * Return the appropriate handler for particular signature list types found in
93 * the UEFI db and MokListRT tables.
94 */
95 static __init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
96 {
97 if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
98 return add_trusted_secondary_key;
99 return 0;
100 }
101
102 /*
103 * Return the appropriate handler for particular signature list types found in
104 * the UEFI dbx and MokListXRT tables.
105 */
106 static __init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type)
107 {
108 if (efi_guidcmp(*sig_type, efi_cert_x509_sha256_guid) == 0)
109 return uefi_blacklist_x509_tbs;
110 if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
111 return uefi_blacklist_binary;
112 return 0;
113 }
114
115 /*
116 * Load the certs contained in the UEFI databases
117 */
118 static int __init load_uefi_certs(void)
119 {
120 efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
121 efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
122 void *db = NULL, *dbx = NULL, *mok = NULL;
123 unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
124 int rc = 0;
125
126 if (!efi.get_variable)
127 return false;
128
129 /* Get db, MokListRT, and dbx. They might not exist, so it isn't
130 * an error if we can't get them.
131 */
132 db = get_cert_list(L"db", &secure_var, &dbsize);
133 if (!db) {
134 pr_err("MODSIGN: Couldn't get UEFI db list\n");
135 } else {
136 rc = parse_efi_signature_list("UEFI:db",
137 db, dbsize, get_handler_for_db);
138 if (rc)
139 pr_err("Couldn't parse db signatures: %d\n", rc);
140 kfree(db);
141 }
142
143 mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
144 if (!mok) {
145 pr_info("MODSIGN: Couldn't get UEFI MokListRT\n");
146 } else {
147 rc = parse_efi_signature_list("UEFI:MokListRT",
148 mok, moksize, get_handler_for_db);
149 if (rc)
150 pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
151 kfree(mok);
152 }
153
154 dbx = get_cert_list(L"dbx", &secure_var, &dbxsize);
155 if (!dbx) {
156 pr_info("MODSIGN: Couldn't get UEFI dbx list\n");
157 } else {
158 rc = parse_efi_signature_list("UEFI:dbx",
159 dbx, dbxsize,
160 get_handler_for_dbx);
161 if (rc)
162 pr_err("Couldn't parse dbx signatures: %d\n", rc);
163 kfree(dbx);
164 }
165
166 return rc;
167 }
168 late_initcall(load_uefi_certs);