Skip to content

Commit 734114f

Browse files
committed
KEYS: Add a system blacklist keyring
Add the following: (1) A new system keyring that is used to store information about blacklisted certificates and signatures. (2) A new key type (called 'blacklist') that is used to store a blacklisted hash in its description as a hex string. The key accepts no payload. (3) The ability to configure a list of blacklisted hashes into the kernel at build time. This is done by setting CONFIG_SYSTEM_BLACKLIST_HASH_LIST to the filename of a list of hashes that are in the form: "<hash>", "<hash>", ..., "<hash>" where each <hash> is a hex string representation of the hash and must include all necessary leading zeros to pad the hash to the right size. The above are enabled with CONFIG_SYSTEM_BLACKLIST_KEYRING. Once the kernel is booted, the blacklist keyring can be listed: root@andromeda ~]# keyctl show %:.blacklist Keyring 723359729 ---lswrv 0 0 keyring: .blacklist 676257228 ---lswrv 0 0 \_ blacklist: 123412341234c55c1dcc601ab8e172917706aa32fb5eaf826813547fdf02dd46 The blacklist cannot currently be modified by userspace, but it will be possible to load it, for example, from the UEFI blacklist database. A later commit will make it possible to load blacklisted asymmetric keys in here too. Signed-off-by: David Howells <[email protected]>
1 parent ddb99e1 commit 734114f

7 files changed

+224
-0
lines changed

certs/Kconfig

+18
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,22 @@ config SECONDARY_TRUSTED_KEYRING
6464
those keys are not blacklisted and are vouched for by a key built
6565
into the kernel or already in the secondary trusted keyring.
6666

67+
config SYSTEM_BLACKLIST_KEYRING
68+
bool "Provide system-wide ring of blacklisted keys"
69+
depends on KEYS
70+
help
71+
Provide a system keyring to which blacklisted keys can be added.
72+
Keys in the keyring are considered entirely untrusted. Keys in this
73+
keyring are used by the module signature checking to reject loading
74+
of modules signed with a blacklisted key.
75+
76+
config SYSTEM_BLACKLIST_HASH_LIST
77+
string "Hashes to be preloaded into the system blacklist keyring"
78+
depends on SYSTEM_BLACKLIST_KEYRING
79+
help
80+
If set, this option should be the filename of a list of hashes in the
81+
form "<hash>", "<hash>", ... . This will be included into a C
82+
wrapper to incorporate the list into the kernel. Each <hash> should
83+
be a string of hex digits.
84+
6785
endmenu

certs/Makefile

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
#
44

55
obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
6+
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o
7+
ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),"")
8+
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o
9+
else
10+
obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_nohashes.o
11+
endif
612

713
ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
814

certs/blacklist.c

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/* System hash blacklist.
2+
*
3+
* Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
4+
* Written by David Howells ([email protected])
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public Licence
8+
* as published by the Free Software Foundation; either version
9+
* 2 of the Licence, or (at your option) any later version.
10+
*/
11+
12+
#define pr_fmt(fmt) "blacklist: "fmt
13+
#include <linux/module.h>
14+
#include <linux/slab.h>
15+
#include <linux/key.h>
16+
#include <linux/key-type.h>
17+
#include <linux/sched.h>
18+
#include <linux/ctype.h>
19+
#include <linux/err.h>
20+
#include <linux/seq_file.h>
21+
#include <keys/system_keyring.h>
22+
#include "blacklist.h"
23+
24+
static struct key *blacklist_keyring;
25+
26+
/*
27+
* The description must be a type prefix, a colon and then an even number of
28+
* hex digits. The hash is kept in the description.
29+
*/
30+
static int blacklist_vet_description(const char *desc)
31+
{
32+
int n = 0;
33+
34+
if (*desc == ':')
35+
return -EINVAL;
36+
for (; *desc; desc++)
37+
if (*desc == ':')
38+
goto found_colon;
39+
return -EINVAL;
40+
41+
found_colon:
42+
desc++;
43+
for (; *desc; desc++) {
44+
if (!isxdigit(*desc))
45+
return -EINVAL;
46+
n++;
47+
}
48+
49+
if (n == 0 || n & 1)
50+
return -EINVAL;
51+
return 0;
52+
}
53+
54+
/*
55+
* The hash to be blacklisted is expected to be in the description. There will
56+
* be no payload.
57+
*/
58+
static int blacklist_preparse(struct key_preparsed_payload *prep)
59+
{
60+
if (prep->datalen > 0)
61+
return -EINVAL;
62+
return 0;
63+
}
64+
65+
static void blacklist_free_preparse(struct key_preparsed_payload *prep)
66+
{
67+
}
68+
69+
static void blacklist_describe(const struct key *key, struct seq_file *m)
70+
{
71+
seq_puts(m, key->description);
72+
}
73+
74+
static struct key_type key_type_blacklist = {
75+
.name = "blacklist",
76+
.vet_description = blacklist_vet_description,
77+
.preparse = blacklist_preparse,
78+
.free_preparse = blacklist_free_preparse,
79+
.instantiate = generic_key_instantiate,
80+
.describe = blacklist_describe,
81+
};
82+
83+
/**
84+
* mark_hash_blacklisted - Add a hash to the system blacklist
85+
* @hash - The hash as a hex string with a type prefix (eg. "tbs:23aa429783")
86+
*/
87+
int mark_hash_blacklisted(const char *hash)
88+
{
89+
key_ref_t key;
90+
91+
key = key_create_or_update(make_key_ref(blacklist_keyring, true),
92+
"blacklist",
93+
hash,
94+
NULL,
95+
0,
96+
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
97+
KEY_USR_VIEW),
98+
KEY_ALLOC_NOT_IN_QUOTA |
99+
KEY_ALLOC_BUILT_IN);
100+
if (IS_ERR(key)) {
101+
pr_err("Problem blacklisting hash (%ld)\n", PTR_ERR(key));
102+
return PTR_ERR(key);
103+
}
104+
return 0;
105+
}
106+
107+
/**
108+
* is_hash_blacklisted - Determine if a hash is blacklisted
109+
* @hash: The hash to be checked as a binary blob
110+
* @hash_len: The length of the binary hash
111+
* @type: Type of hash
112+
*/
113+
int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type)
114+
{
115+
key_ref_t kref;
116+
size_t type_len = strlen(type);
117+
char *buffer, *p;
118+
int ret = 0;
119+
120+
buffer = kmalloc(type_len + 1 + hash_len * 2 + 1, GFP_KERNEL);
121+
if (!buffer)
122+
return -ENOMEM;
123+
p = memcpy(buffer, type, type_len);
124+
p += type_len;
125+
*p++ = ':';
126+
bin2hex(p, hash, hash_len);
127+
p += hash_len * 2;
128+
*p = 0;
129+
130+
kref = keyring_search(make_key_ref(blacklist_keyring, true),
131+
&key_type_blacklist, buffer);
132+
if (!IS_ERR(kref)) {
133+
key_ref_put(kref);
134+
ret = -EKEYREJECTED;
135+
}
136+
137+
kfree(buffer);
138+
return ret;
139+
}
140+
EXPORT_SYMBOL_GPL(is_hash_blacklisted);
141+
142+
/*
143+
* Intialise the blacklist
144+
*/
145+
static int __init blacklist_init(void)
146+
{
147+
const char *const *bl;
148+
149+
if (register_key_type(&key_type_blacklist) < 0)
150+
panic("Can't allocate system blacklist key type\n");
151+
152+
blacklist_keyring =
153+
keyring_alloc(".blacklist",
154+
KUIDT_INIT(0), KGIDT_INIT(0),
155+
current_cred(),
156+
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
157+
KEY_USR_VIEW | KEY_USR_READ |
158+
KEY_USR_SEARCH,
159+
KEY_ALLOC_NOT_IN_QUOTA |
160+
KEY_FLAG_KEEP,
161+
NULL, NULL);
162+
if (IS_ERR(blacklist_keyring))
163+
panic("Can't allocate system blacklist keyring\n");
164+
165+
for (bl = blacklist_hashes; *bl; bl++)
166+
if (mark_hash_blacklisted(*bl) < 0)
167+
pr_err("- blacklisting failed\n");
168+
return 0;
169+
}
170+
171+
/*
172+
* Must be initialised before we try and load the keys into the keyring.
173+
*/
174+
device_initcall(blacklist_init);

certs/blacklist.h

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include <linux/kernel.h>
2+
3+
extern const char __initdata *const blacklist_hashes[];

certs/blacklist_hashes.c

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "blacklist.h"
2+
3+
const char __initdata *const blacklist_hashes[] = {
4+
#include CONFIG_SYSTEM_BLACKLIST_HASH_LIST
5+
, NULL
6+
};

certs/blacklist_nohashes.c

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "blacklist.h"
2+
3+
const char __initdata *const blacklist_hashes[] = {
4+
NULL
5+
};

include/keys/system_keyring.h

+12
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
3333
#define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted
3434
#endif
3535

36+
#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
37+
extern int mark_hash_blacklisted(const char *hash);
38+
extern int is_hash_blacklisted(const u8 *hash, size_t hash_len,
39+
const char *type);
40+
#else
41+
static inline int is_hash_blacklisted(const u8 *hash, size_t hash_len,
42+
const char *type)
43+
{
44+
return 0;
45+
}
46+
#endif
47+
3648
#ifdef CONFIG_IMA_BLACKLIST_KEYRING
3749
extern struct key *ima_blacklist_keyring;
3850

0 commit comments

Comments
 (0)