This source file includes following definitions.
- uefi_check_ignore_db
- get_cert_list
- uefi_blacklist_hash
- uefi_blacklist_x509_tbs
- uefi_blacklist_binary
- get_handler_for_db
- get_handler_for_dbx
- load_uefi_certs
1
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
13 static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
14 static efi_guid_t efi_cert_x509_sha256_guid __initdata =
15 EFI_CERT_X509_SHA256_GUID;
16 static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
17
18
19
20
21
22
23
24
25
26
27 static __init bool uefi_check_ignore_db(void)
28 {
29 efi_status_t status;
30 unsigned int db = 0;
31 unsigned long size = sizeof(db);
32 efi_guid_t guid = EFI_SHIM_LOCK_GUID;
33
34 status = efi.get_variable(L"MokIgnoreDB", &guid, NULL, &size, &db);
35 return status == EFI_SUCCESS;
36 }
37
38
39
40
41 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
42 unsigned long *size, efi_status_t *status)
43 {
44 unsigned long lsize = 4;
45 unsigned long tmpdb[4];
46 void *db;
47
48 *status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
49 if (*status == EFI_NOT_FOUND)
50 return NULL;
51
52 if (*status != EFI_BUFFER_TOO_SMALL) {
53 pr_err("Couldn't get size: 0x%lx\n", *status);
54 return NULL;
55 }
56
57 db = kmalloc(lsize, GFP_KERNEL);
58 if (!db)
59 return NULL;
60
61 *status = efi.get_variable(name, guid, NULL, &lsize, db);
62 if (*status != EFI_SUCCESS) {
63 kfree(db);
64 pr_err("Error reading db var: 0x%lx\n", *status);
65 return NULL;
66 }
67
68 *size = lsize;
69 return db;
70 }
71
72
73
74
75 static __init void uefi_blacklist_hash(const char *source, const void *data,
76 size_t len, const char *type,
77 size_t type_len)
78 {
79 char *hash, *p;
80
81 hash = kmalloc(type_len + len * 2 + 1, GFP_KERNEL);
82 if (!hash)
83 return;
84 p = memcpy(hash, type, type_len);
85 p += type_len;
86 bin2hex(p, data, len);
87 p += len * 2;
88 *p = 0;
89
90 mark_hash_blacklisted(hash);
91 kfree(hash);
92 }
93
94
95
96
97 static __init void uefi_blacklist_x509_tbs(const char *source,
98 const void *data, size_t len)
99 {
100 uefi_blacklist_hash(source, data, len, "tbs:", 4);
101 }
102
103
104
105
106 static __init void uefi_blacklist_binary(const char *source,
107 const void *data, size_t len)
108 {
109 uefi_blacklist_hash(source, data, len, "bin:", 4);
110 }
111
112
113
114
115
116 static __init efi_element_handler_t get_handler_for_db(const efi_guid_t *
117 sig_type)
118 {
119 if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
120 return add_to_platform_keyring;
121 return 0;
122 }
123
124
125
126
127
128 static __init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *
129 sig_type)
130 {
131 if (efi_guidcmp(*sig_type, efi_cert_x509_sha256_guid) == 0)
132 return uefi_blacklist_x509_tbs;
133 if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
134 return uefi_blacklist_binary;
135 return 0;
136 }
137
138
139
140
141
142
143 static int __init load_uefi_certs(void)
144 {
145 efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
146 efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
147 void *db = NULL, *dbx = NULL, *mok = NULL;
148 unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
149 efi_status_t status;
150 int rc = 0;
151
152 if (!efi.get_variable)
153 return false;
154
155
156
157
158 if (!uefi_check_ignore_db()) {
159 db = get_cert_list(L"db", &secure_var, &dbsize, &status);
160 if (!db) {
161 if (status == EFI_NOT_FOUND)
162 pr_debug("MODSIGN: db variable wasn't found\n");
163 else
164 pr_err("MODSIGN: Couldn't get UEFI db list\n");
165 } else {
166 rc = parse_efi_signature_list("UEFI:db",
167 db, dbsize, get_handler_for_db);
168 if (rc)
169 pr_err("Couldn't parse db signatures: %d\n",
170 rc);
171 kfree(db);
172 }
173 }
174
175 mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status);
176 if (!mok) {
177 if (status == EFI_NOT_FOUND)
178 pr_debug("MokListRT variable wasn't found\n");
179 else
180 pr_info("Couldn't get UEFI MokListRT\n");
181 } else {
182 rc = parse_efi_signature_list("UEFI:MokListRT",
183 mok, moksize, get_handler_for_db);
184 if (rc)
185 pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
186 kfree(mok);
187 }
188
189 dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status);
190 if (!dbx) {
191 if (status == EFI_NOT_FOUND)
192 pr_debug("dbx variable wasn't found\n");
193 else
194 pr_info("Couldn't get UEFI dbx list\n");
195 } else {
196 rc = parse_efi_signature_list("UEFI:dbx",
197 dbx, dbxsize,
198 get_handler_for_dbx);
199 if (rc)
200 pr_err("Couldn't parse dbx signatures: %d\n", rc);
201 kfree(dbx);
202 }
203
204 return rc;
205 }
206 late_initcall(load_uefi_certs);