certs: Check that builtin blacklist hashes are valid
authorMickaël Salaün <mic@linux.microsoft.com>
Mon, 12 Jul 2021 17:03:10 +0000 (19:03 +0200)
committerJarkko Sakkinen <jarkko@kernel.org>
Mon, 23 May 2022 15:47:49 +0000 (18:47 +0300)
Add and use a check-blacklist-hashes.awk script to make sure that the
builtin blacklist hashes set with CONFIG_SYSTEM_BLACKLIST_HASH_LIST will
effectively be taken into account as blacklisted hashes.  This is useful
to debug invalid hash formats, and it make sure that previous hashes
which could have been loaded in the kernel, but silently ignored, are
now noticed and deal with by the user at kernel build time.

This also prevent stricter blacklist key description checking (provided
by following commits) to failed for builtin hashes.

Update CONFIG_SYSTEM_BLACKLIST_HASH_LIST help to explain the content of
a hash string and how to generate certificate ones.

Cc: David Howells <dhowells@redhat.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Eric Snowberg <eric.snowberg@oracle.com>
Cc: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Mickaël Salaün <mic@linux.microsoft.com>
Link: https://lore.kernel.org/r/20210712170313.884724-3-mic@digikod.net
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
MAINTAINERS
certs/.gitignore
certs/Kconfig
certs/Makefile
scripts/check-blacklist-hashes.awk [new file with mode: 0755]

index 4f2a63b0ec3bfebb6ecfb9c1b23098b4f3367acc..bf41a67635ec4288efb0f71d7cd7355fed3ba857 100644 (file)
@@ -4575,6 +4575,7 @@ L:        keyrings@vger.kernel.org
 S:     Maintained
 F:     Documentation/admin-guide/module-signing.rst
 F:     certs/
+F:     scripts/check-blacklist-hashes.awk
 F:     scripts/sign-file.c
 F:     tools/certs/
 
index 9e42fe3e02f569ca1ad05c70d87f42918542a76d..56637aceaf81c62cfe63cfe6a10fe7e82835266b 100644 (file)
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
+/blacklist_hashes_checked
 /extract-cert
 /x509_certificate_list
 /x509_revocation_list
index 73d1350c223a8c757dff74a3ce1dbc5d6a9e9a11..4bd385b25084848a0ccc74a6a21ea18efaa97769 100644 (file)
@@ -104,8 +104,11 @@ config SYSTEM_BLACKLIST_HASH_LIST
        help
          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> should
-         be a string of hex digits.
+         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).
+         Certificate hashes can be generated with
+         tools/certs/print-cert-tbs-hash.sh .
 
 config SYSTEM_REVOCATION_LIST
        bool "Provide system-wide ring of revocation certificates"
index d8443cfb1c401ae51bec3a34b681ea4090149c5f..1d26ae36af20d5621be62b73a15929d078018e93 100644 (file)
@@ -7,6 +7,18 @@ obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o c
 obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o common.o
 obj-$(CONFIG_SYSTEM_REVOCATION_LIST) += revocation_certificates.o
 ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),)
+quiet_cmd_check_blacklist_hashes = CHECK   $(patsubst "%",%,$(2))
+      cmd_check_blacklist_hashes = $(AWK) -f $(srctree)/scripts/check-blacklist-hashes.awk $(2); touch $@
+
+$(eval $(call config_filename,SYSTEM_BLACKLIST_HASH_LIST))
+
+$(obj)/blacklist_hashes.o: $(obj)/blacklist_hashes_checked
+
+CFLAGS_blacklist_hashes.o += -I$(srctree)
+
+targets += blacklist_hashes_checked
+$(obj)/blacklist_hashes_checked: $(SYSTEM_BLACKLIST_HASH_LIST_SRCPREFIX)$(SYSTEM_BLACKLIST_HASH_LIST_FILENAME) scripts/check-blacklist-hashes.awk FORCE
+       $(call if_changed,check_blacklist_hashes,$(SYSTEM_BLACKLIST_HASH_LIST_SRCPREFIX)$(CONFIG_SYSTEM_BLACKLIST_HASH_LIST))
 obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o
 else
 obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_nohashes.o
@@ -21,7 +33,7 @@ $(obj)/system_certificates.o: $(obj)/x509_certificate_list
 $(obj)/x509_certificate_list: $(CONFIG_SYSTEM_TRUSTED_KEYS) $(obj)/extract-cert FORCE
        $(call if_changed,extract_certs)
 
-targets += x509_certificate_list
+targets += x509_certificate_list blacklist_hashes_checked
 
 # If module signing is requested, say by allyesconfig, but a key has not been
 # supplied, then one will need to be generated to make sure the build does not
diff --git a/scripts/check-blacklist-hashes.awk b/scripts/check-blacklist-hashes.awk
new file mode 100755 (executable)
index 0000000..107c1d3
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/awk -f
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright © 2020, Microsoft Corporation. All rights reserved.
+#
+# Author: Mickaël Salaün <mic@linux.microsoft.com>
+#
+# Check that a CONFIG_SYSTEM_BLACKLIST_HASH_LIST file contains a valid array of
+# hash strings.  Such string must start with a prefix ("tbs" or "bin"), then a
+# colon (":"), and finally an even number of hexadecimal lowercase characters
+# (up to 128).
+
+BEGIN {
+       RS = ","
+}
+{
+       if (!match($0, "^[ \t\n\r]*\"([^\"]*)\"[ \t\n\r]*$", part1)) {
+               print "Not a string (item " NR "):", $0;
+               exit 1;
+       }
+       if (!match(part1[1], "^(tbs|bin):(.*)$", part2)) {
+               print "Unknown prefix (item " NR "):", part1[1];
+               exit 1;
+       }
+       if (!match(part2[2], "^([0-9a-f]+)$", part3)) {
+               print "Not a lowercase hexadecimal string (item " NR "):", part2[2];
+               exit 1;
+       }
+       if (length(part3[1]) > 128) {
+               print "Hash string too long (item " NR "):", part3[1];
+               exit 1;
+       }
+       if (length(part3[1]) % 2 == 1) {
+               print "Not an even number of hexadecimal characters (item " NR "):", part3[1];
+               exit 1;
+       }
+}