1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* System hash blacklist.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
5*4882a593Smuzhiyun * Written by David Howells (dhowells@redhat.com)
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #define pr_fmt(fmt) "blacklist: "fmt
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include <linux/key.h>
12*4882a593Smuzhiyun #include <linux/key-type.h>
13*4882a593Smuzhiyun #include <linux/sched.h>
14*4882a593Smuzhiyun #include <linux/ctype.h>
15*4882a593Smuzhiyun #include <linux/err.h>
16*4882a593Smuzhiyun #include <linux/seq_file.h>
17*4882a593Smuzhiyun #include <keys/system_keyring.h>
18*4882a593Smuzhiyun #include "blacklist.h"
19*4882a593Smuzhiyun #include "common.h"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun static struct key *blacklist_keyring;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #ifdef CONFIG_SYSTEM_REVOCATION_LIST
24*4882a593Smuzhiyun extern __initconst const u8 revocation_certificate_list[];
25*4882a593Smuzhiyun extern __initconst const unsigned long revocation_certificate_list_size;
26*4882a593Smuzhiyun #endif
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun * The description must be a type prefix, a colon and then an even number of
30*4882a593Smuzhiyun * hex digits. The hash is kept in the description.
31*4882a593Smuzhiyun */
blacklist_vet_description(const char * desc)32*4882a593Smuzhiyun static int blacklist_vet_description(const char *desc)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun int n = 0;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun if (*desc == ':')
37*4882a593Smuzhiyun return -EINVAL;
38*4882a593Smuzhiyun for (; *desc; desc++)
39*4882a593Smuzhiyun if (*desc == ':')
40*4882a593Smuzhiyun goto found_colon;
41*4882a593Smuzhiyun return -EINVAL;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun found_colon:
44*4882a593Smuzhiyun desc++;
45*4882a593Smuzhiyun for (; *desc; desc++) {
46*4882a593Smuzhiyun if (!isxdigit(*desc))
47*4882a593Smuzhiyun return -EINVAL;
48*4882a593Smuzhiyun n++;
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun if (n == 0 || n & 1)
52*4882a593Smuzhiyun return -EINVAL;
53*4882a593Smuzhiyun return 0;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /*
57*4882a593Smuzhiyun * The hash to be blacklisted is expected to be in the description. There will
58*4882a593Smuzhiyun * be no payload.
59*4882a593Smuzhiyun */
blacklist_preparse(struct key_preparsed_payload * prep)60*4882a593Smuzhiyun static int blacklist_preparse(struct key_preparsed_payload *prep)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun if (prep->datalen > 0)
63*4882a593Smuzhiyun return -EINVAL;
64*4882a593Smuzhiyun return 0;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
blacklist_free_preparse(struct key_preparsed_payload * prep)67*4882a593Smuzhiyun static void blacklist_free_preparse(struct key_preparsed_payload *prep)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
blacklist_describe(const struct key * key,struct seq_file * m)71*4882a593Smuzhiyun static void blacklist_describe(const struct key *key, struct seq_file *m)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun seq_puts(m, key->description);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun static struct key_type key_type_blacklist = {
77*4882a593Smuzhiyun .name = "blacklist",
78*4882a593Smuzhiyun .vet_description = blacklist_vet_description,
79*4882a593Smuzhiyun .preparse = blacklist_preparse,
80*4882a593Smuzhiyun .free_preparse = blacklist_free_preparse,
81*4882a593Smuzhiyun .instantiate = generic_key_instantiate,
82*4882a593Smuzhiyun .describe = blacklist_describe,
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /**
86*4882a593Smuzhiyun * mark_hash_blacklisted - Add a hash to the system blacklist
87*4882a593Smuzhiyun * @hash - The hash as a hex string with a type prefix (eg. "tbs:23aa429783")
88*4882a593Smuzhiyun */
mark_hash_blacklisted(const char * hash)89*4882a593Smuzhiyun int mark_hash_blacklisted(const char *hash)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun key_ref_t key;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun key = key_create_or_update(make_key_ref(blacklist_keyring, true),
94*4882a593Smuzhiyun "blacklist",
95*4882a593Smuzhiyun hash,
96*4882a593Smuzhiyun NULL,
97*4882a593Smuzhiyun 0,
98*4882a593Smuzhiyun ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
99*4882a593Smuzhiyun KEY_USR_VIEW),
100*4882a593Smuzhiyun KEY_ALLOC_NOT_IN_QUOTA |
101*4882a593Smuzhiyun KEY_ALLOC_BUILT_IN);
102*4882a593Smuzhiyun if (IS_ERR(key)) {
103*4882a593Smuzhiyun pr_err("Problem blacklisting hash (%ld)\n", PTR_ERR(key));
104*4882a593Smuzhiyun return PTR_ERR(key);
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun return 0;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /**
110*4882a593Smuzhiyun * is_hash_blacklisted - Determine if a hash is blacklisted
111*4882a593Smuzhiyun * @hash: The hash to be checked as a binary blob
112*4882a593Smuzhiyun * @hash_len: The length of the binary hash
113*4882a593Smuzhiyun * @type: Type of hash
114*4882a593Smuzhiyun */
is_hash_blacklisted(const u8 * hash,size_t hash_len,const char * type)115*4882a593Smuzhiyun int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun key_ref_t kref;
118*4882a593Smuzhiyun size_t type_len = strlen(type);
119*4882a593Smuzhiyun char *buffer, *p;
120*4882a593Smuzhiyun int ret = 0;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun buffer = kmalloc(type_len + 1 + hash_len * 2 + 1, GFP_KERNEL);
123*4882a593Smuzhiyun if (!buffer)
124*4882a593Smuzhiyun return -ENOMEM;
125*4882a593Smuzhiyun p = memcpy(buffer, type, type_len);
126*4882a593Smuzhiyun p += type_len;
127*4882a593Smuzhiyun *p++ = ':';
128*4882a593Smuzhiyun bin2hex(p, hash, hash_len);
129*4882a593Smuzhiyun p += hash_len * 2;
130*4882a593Smuzhiyun *p = 0;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun kref = keyring_search(make_key_ref(blacklist_keyring, true),
133*4882a593Smuzhiyun &key_type_blacklist, buffer, false);
134*4882a593Smuzhiyun if (!IS_ERR(kref)) {
135*4882a593Smuzhiyun key_ref_put(kref);
136*4882a593Smuzhiyun ret = -EKEYREJECTED;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun kfree(buffer);
140*4882a593Smuzhiyun return ret;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(is_hash_blacklisted);
143*4882a593Smuzhiyun
is_binary_blacklisted(const u8 * hash,size_t hash_len)144*4882a593Smuzhiyun int is_binary_blacklisted(const u8 *hash, size_t hash_len)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun if (is_hash_blacklisted(hash, hash_len, "bin") == -EKEYREJECTED)
147*4882a593Smuzhiyun return -EPERM;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun return 0;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(is_binary_blacklisted);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun #ifdef CONFIG_SYSTEM_REVOCATION_LIST
154*4882a593Smuzhiyun /**
155*4882a593Smuzhiyun * add_key_to_revocation_list - Add a revocation certificate to the blacklist
156*4882a593Smuzhiyun * @data: The data blob containing the certificate
157*4882a593Smuzhiyun * @size: The size of data blob
158*4882a593Smuzhiyun */
add_key_to_revocation_list(const char * data,size_t size)159*4882a593Smuzhiyun int add_key_to_revocation_list(const char *data, size_t size)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun key_ref_t key;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun key = key_create_or_update(make_key_ref(blacklist_keyring, true),
164*4882a593Smuzhiyun "asymmetric",
165*4882a593Smuzhiyun NULL,
166*4882a593Smuzhiyun data,
167*4882a593Smuzhiyun size,
168*4882a593Smuzhiyun ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW),
169*4882a593Smuzhiyun KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_BUILT_IN);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (IS_ERR(key)) {
172*4882a593Smuzhiyun pr_err("Problem with revocation key (%ld)\n", PTR_ERR(key));
173*4882a593Smuzhiyun return PTR_ERR(key);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun return 0;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /**
180*4882a593Smuzhiyun * is_key_on_revocation_list - Determine if the key for a PKCS#7 message is revoked
181*4882a593Smuzhiyun * @pkcs7: The PKCS#7 message to check
182*4882a593Smuzhiyun */
is_key_on_revocation_list(struct pkcs7_message * pkcs7)183*4882a593Smuzhiyun int is_key_on_revocation_list(struct pkcs7_message *pkcs7)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun int ret;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun ret = pkcs7_validate_trust(pkcs7, blacklist_keyring);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (ret == 0)
190*4882a593Smuzhiyun return -EKEYREJECTED;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun return -ENOKEY;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun #endif
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun /*
197*4882a593Smuzhiyun * Initialise the blacklist
198*4882a593Smuzhiyun */
blacklist_init(void)199*4882a593Smuzhiyun static int __init blacklist_init(void)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun const char *const *bl;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun if (register_key_type(&key_type_blacklist) < 0)
204*4882a593Smuzhiyun panic("Can't allocate system blacklist key type\n");
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun blacklist_keyring =
207*4882a593Smuzhiyun keyring_alloc(".blacklist",
208*4882a593Smuzhiyun KUIDT_INIT(0), KGIDT_INIT(0),
209*4882a593Smuzhiyun current_cred(),
210*4882a593Smuzhiyun (KEY_POS_ALL & ~KEY_POS_SETATTR) |
211*4882a593Smuzhiyun KEY_USR_VIEW | KEY_USR_READ |
212*4882a593Smuzhiyun KEY_USR_SEARCH,
213*4882a593Smuzhiyun KEY_ALLOC_NOT_IN_QUOTA |
214*4882a593Smuzhiyun KEY_ALLOC_SET_KEEP,
215*4882a593Smuzhiyun NULL, NULL);
216*4882a593Smuzhiyun if (IS_ERR(blacklist_keyring))
217*4882a593Smuzhiyun panic("Can't allocate system blacklist keyring\n");
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun for (bl = blacklist_hashes; *bl; bl++)
220*4882a593Smuzhiyun if (mark_hash_blacklisted(*bl) < 0)
221*4882a593Smuzhiyun pr_err("- blacklisting failed\n");
222*4882a593Smuzhiyun return 0;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /*
226*4882a593Smuzhiyun * Must be initialised before we try and load the keys into the keyring.
227*4882a593Smuzhiyun */
228*4882a593Smuzhiyun device_initcall(blacklist_init);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun #ifdef CONFIG_SYSTEM_REVOCATION_LIST
231*4882a593Smuzhiyun /*
232*4882a593Smuzhiyun * Load the compiled-in list of revocation X.509 certificates.
233*4882a593Smuzhiyun */
load_revocation_certificate_list(void)234*4882a593Smuzhiyun static __init int load_revocation_certificate_list(void)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun if (revocation_certificate_list_size)
237*4882a593Smuzhiyun pr_notice("Loading compiled-in revocation X.509 certificates\n");
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun return load_certificate_list(revocation_certificate_list, revocation_certificate_list_size,
240*4882a593Smuzhiyun blacklist_keyring);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun late_initcall(load_revocation_certificate_list);
243*4882a593Smuzhiyun #endif
244