From: Mimi Zohar <zohar@linux.ibm.com>
To: linux-integrity@vger.kernel.org
Cc: Mimi Zohar <zohar@linux.ibm.com>,
Jarkko Sakkinen <jarkko@kernel.org>,
David Howells <dhowells@redhat.com>,
Roberto Sassu <roberto.sassu@huawei.com>,
keyrings@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH 1/3] certs: blacklist: define skid: entries and add is_key_blacklisted()
Date: Thu, 5 Nov 2026 07:12:25 -0500 [thread overview]
Message-ID: <20261105121227.4089147-2-zohar@linux.ibm.com> (raw)
In-Reply-To: <20261105121227.4089147-1-zohar@linux.ibm.com>
A "tbs:" blacklist entry is only compared against certificates being
added to a keyring or presented in a signature chain, so it does not
stop a key that is already loaded from being used as a trust anchor.
Define a new "skid:<hex>" blacklist entry, holding a Subject Key
Identifier, and add is_key_blacklisted(), which looks up the SKID of an
asymmetric key in the system blacklist. Entries are added like "tbs:"
and "bin:" entries and are subject to CONFIG_SYSTEM_BLACKLIST_AUTH_UPDATE.
blacklist_vet_description() now uses a prefix table, since the prefixes
no longer all have the same length. "tbs:" and "bin:" entries behave
as before.
For example, to add an entry for a certificate (the signed string must
not include a trailing newline):
skid=$(openssl x509 -in cert.pem -noout -ext subjectKeyIdentifier |
sed -n '2s/[ :]//gp' | tr A-F a-f)
printf 'skid:%s' "$skid" > skid.txt
openssl smime -sign -binary -noattr -in skid.txt -signer signer.crt \
-inkey signer.key -outform DER -out skid.p7s
keyctl padd blacklist "skid:$skid" %:.blacklist < skid.p7s
The SKID is also the hex string in the description of the key on a
keyring, and its last four bytes are the key ID in the security.ima
xattr, so an entry is easy to correlate with the key it revokes:
# keyctl show %:.ima | grep 073d
927946571 --als--v 0 0 \_ asymmetric: test signing key: b7809c3372a07fe87248dcec7ff047a40fb3073d
# keyctl show %:.blacklist | grep skid
1014808518 ----s--v 0 0 \_ blacklist: skid:b7809c3372a07fe87248dcec7ff047a40fb3073d
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
---
certs/Kconfig | 7 +--
certs/blacklist.c | 81 ++++++++++++++++++++++++-----------
include/keys/system_keyring.h | 8 ++++
3 files changed, 68 insertions(+), 28 deletions(-)
diff --git a/certs/Kconfig b/certs/Kconfig
index 9d2bf7fb5b9e..9e51f988ba3b 100644
--- a/certs/Kconfig
+++ b/certs/Kconfig
@@ -155,10 +155,11 @@ config SYSTEM_BLACKLIST_HASH_LIST
If set, this option should be the filename of a list of hashes in the
form "<hash>", "<hash>", ... . This will be included into a C
wrapper to incorporate the list into the kernel. Each <hash> must be a
- string starting with a prefix ("tbs" or "bin"), then a colon (":"), and
- finally an even number of hexadecimal lowercase characters (up to 128).
+ string starting with a prefix ("tbs", "bin" or "skid"), then a colon
+ (":"), and finally an even number of hexadecimal lowercase characters
+ (up to 128).
Certificate hashes can be generated with
- tools/certs/print-cert-tbs-hash.sh .
+ tools/certs/print-cert-tbs-hash.sh.
config SYSTEM_REVOCATION_LIST
bool "Provide system-wide ring of revocation certificates"
diff --git a/certs/blacklist.c b/certs/blacklist.c
index fa561c12eabf..b1e2c178d378 100644
--- a/certs/blacklist.c
+++ b/certs/blacklist.c
@@ -32,6 +32,7 @@
static const char tbs_prefix[] = "tbs";
static const char bin_prefix[] = "bin";
+static const char skid_prefix[] = "skid";
static struct key *blacklist_keyring;
@@ -40,36 +41,30 @@ extern __initconst const u8 revocation_certificate_list[];
extern __initconst const unsigned long revocation_certificate_list_size;
#endif
+static bool blacklist_prefix_valid(const char *desc, size_t len)
+{
+ return (len == sizeof(tbs_prefix) - 1 &&
+ !strncmp(desc, tbs_prefix, len)) ||
+ (len == sizeof(bin_prefix) - 1 &&
+ !strncmp(desc, bin_prefix, len)) ||
+ (len == sizeof(skid_prefix) - 1 &&
+ !strncmp(desc, skid_prefix, len));
+}
+
/*
- * The description must be a type prefix, a colon and then an even number of
- * hex digits. The hash is kept in the description.
+ * The description must be a type prefix ("tbs", "bin" or "skid"), a colon and
+ * then an even number of lower-case hex digits. The hash (or, for "skid", the
+ * Subject Key Identifier) is kept in the description.
*/
static int blacklist_vet_description(const char *desc)
{
- int i, prefix_len, tbs_step = 0, bin_step = 0;
-
- /* The following algorithm only works if prefix lengths match. */
- BUILD_BUG_ON(sizeof(tbs_prefix) != sizeof(bin_prefix));
- prefix_len = sizeof(tbs_prefix) - 1;
- for (i = 0; *desc; desc++, i++) {
- if (*desc == ':') {
- if (tbs_step == prefix_len)
- goto found_colon;
- if (bin_step == prefix_len)
- goto found_colon;
- return -EINVAL;
- }
- if (i >= prefix_len)
- return -EINVAL;
- if (*desc == tbs_prefix[i])
- tbs_step++;
- if (*desc == bin_prefix[i])
- bin_step++;
- }
- return -EINVAL;
+ const char *colon = strchr(desc, ':');
+ int i;
-found_colon:
- desc++;
+ if (!colon || !blacklist_prefix_valid(desc, colon - desc))
+ return -EINVAL;
+
+ desc = colon + 1;
for (i = 0; *desc && i < MAX_HASH_LEN; desc++, i++) {
if (!isxdigit(*desc) || isupper(*desc))
return -EINVAL;
@@ -160,6 +155,10 @@ static char *get_raw_hash(const u8 *hash, size_t hash_len,
type_len = sizeof(bin_prefix) - 1;
type_prefix = bin_prefix;
break;
+ case BLACKLIST_HASH_SKID:
+ type_len = sizeof(skid_prefix) - 1;
+ type_prefix = skid_prefix;
+ break;
default:
WARN_ON_ONCE(1);
return ERR_PTR(-EINVAL);
@@ -244,6 +243,38 @@ int is_hash_blacklisted(const u8 *hash, size_t hash_len,
}
EXPORT_SYMBOL_GPL(is_hash_blacklisted);
+/**
+ * is_key_blacklisted - Determine if a key is blacklisted by its SKID
+ * @key: The key to be checked, e.g. a trust anchor found in a keyring
+ *
+ * Unlike a "tbs:" entry, which is only compared against certificates being
+ * added or presented in a chain, this checks a key that is already loaded, so
+ * that keys that cannot be unlinked from their keyring can still be revoked.
+ * The identifier is taken from the key itself, not from the caller.
+ *
+ * Returns -EKEYREJECTED if the key's Subject Key Identifier is blacklisted,
+ * 0 if it is not (or the key has no SKID), or another negative error.
+ */
+int is_key_blacklisted(const struct key *key)
+{
+ const struct asymmetric_key_ids *kids;
+ const struct asymmetric_key_id *skid;
+
+ if (!key || key->type != &key_type_asymmetric)
+ return 0;
+
+ kids = asymmetric_key_ids(key);
+ if (!kids)
+ return 0;
+
+ skid = kids->id[1];
+ if (!skid || !skid->len)
+ return 0;
+
+ return is_hash_blacklisted(skid->data, skid->len, BLACKLIST_HASH_SKID);
+}
+EXPORT_SYMBOL_GPL(is_key_blacklisted);
+
int is_binary_blacklisted(const u8 *hash, size_t hash_len)
{
if (is_hash_blacklisted(hash, hash_len, BLACKLIST_HASH_BINARY) ==
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index a6c2897bcc63..48c830850b70 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -15,6 +15,8 @@ enum blacklist_hash_type {
BLACKLIST_HASH_X509_TBS = 1,
/* Raw data hash */
BLACKLIST_HASH_BINARY = 2,
+ /* Subject Key Identifier of a key (not a hash) */
+ BLACKLIST_HASH_SKID = 3,
};
#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING
@@ -79,6 +81,7 @@ extern int mark_hash_blacklisted(const u8 *hash, size_t hash_len,
extern int is_hash_blacklisted(const u8 *hash, size_t hash_len,
enum blacklist_hash_type hash_type);
extern int is_binary_blacklisted(const u8 *hash, size_t hash_len);
+extern int is_key_blacklisted(const struct key *key);
#else
static inline int is_hash_blacklisted(const u8 *hash, size_t hash_len,
enum blacklist_hash_type hash_type)
@@ -90,6 +93,11 @@ static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len)
{
return 0;
}
+
+static inline int is_key_blacklisted(const struct key *key)
+{
+ return 0;
+}
#endif
struct pkcs7_message;
--
2.56.0
next prev parent reply other threads:[~2026-11-05 12:12 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 12:12 [RFC PATCH 0/3] ima: use the system blacklist in lieu of the IMA blacklist keyring Mimi Zohar
2026-11-05 12:12 ` Mimi Zohar [this message]
2026-11-05 12:22 ` [RFC PATCH 1/3] certs: blacklist: define skid: entries and add is_key_blacklisted() sashiko-bot
2026-11-05 12:12 ` [RFC PATCH 2/3] integrity: use is_key_blacklisted() in asymmetric_verify() Mimi Zohar
2026-11-05 12:12 ` [RFC PATCH 3/3] ima: remove the experimental IMA blacklist keyring Mimi Zohar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261105121227.4089147-2-zohar@linux.ibm.com \
--to=zohar@linux.ibm.com \
--cc=dhowells@redhat.com \
--cc=jarkko@kernel.org \
--cc=keyrings@vger.kernel.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=roberto.sassu@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.