From 99d27b1b52bd5cdf9bd9f7661ca8641e9a1b55e6 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 20 Jul 2015 21:16:31 +0100 Subject: modsign: Add explicit CONFIG_SYSTEM_TRUSTED_KEYS option Let the user explicitly provide a file containing trusted keys, instead of just automatically finding files matching *.x509 in the build tree and trusting whatever we find. This really ought to be an *explicit* configuration, and the build rules for dealing with the files were fairly painful too. Fix applied from James Morris that removes an '=' from a macro definition in kernel/Makefile as this is a feature that only exists from GNU make 3.82 onwards. Signed-off-by: David Woodhouse Signed-off-by: David Howells --- kernel/Makefile | 125 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 60 deletions(-) (limited to 'kernel/Makefile') diff --git a/kernel/Makefile b/kernel/Makefile index 7453283..5753297 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -114,46 +114,75 @@ $(obj)/config_data.h: $(obj)/config_data.gz FORCE ############################################################################### # -# Roll all the X.509 certificates that we can find together and pull them into -# the kernel so that they get loaded into the system trusted keyring during -# boot. +# When a Kconfig string contains a filename, it is suitable for +# passing to shell commands. It is surrounded by double-quotes, and +# any double-quotes or backslashes within it are escaped by +# backslashes. # -# We look in the source root and the build root for all files whose name ends -# in ".x509". Unfortunately, this will generate duplicate filenames, so we -# have make canonicalise the pathnames and then sort them to discard the -# duplicates. +# This is no use for dependencies or $(wildcard). We need to strip the +# surrounding quotes and the escaping from quotes and backslashes, and +# we *do* need to escape any spaces in the string. So, for example: +# +# Usage: $(eval $(call config_filename,FOO)) +# +# Defines FOO_FILENAME based on the contents of the CONFIG_FOO option, +# transformed as described above to be suitable for use within the +# makefile. +# +# Also, if the filename is a relative filename and exists in the source +# tree but not the build tree, define FOO_SRCPREFIX as $(srctree)/ to +# be prefixed to *both* command invocation and dependencies. +# +# Note: We also print the filenames in the quiet_cmd_foo text, and +# perhaps ought to have a version specially escaped for that purpose. +# But it's only cosmetic, and $(patsubst "%",%,$(CONFIG_FOO)) is good +# enough. It'll strip the quotes in the common case where there's no +# space and it's a simple filename, and it'll retain the quotes when +# there's a space. There are some esoteric cases in which it'll print +# the wrong thing, but we don't really care. The actual dependencies +# and commands *do* get it right, with various combinations of single +# and double quotes, backslashes and spaces in the filenames. # ############################################################################### -ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) -X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) -X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += $(objtree)/signing_key.x509 -X509_CERTIFICATES-raw := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \ - $(or $(realpath $(CERT)),$(CERT)))) -X509_CERTIFICATES := $(subst $(realpath $(objtree))/,,$(X509_CERTIFICATES-raw)) - -ifeq ($(X509_CERTIFICATES),) -$(warning *** No X.509 certificates found ***) +# +quote := $(firstword " ") +space := +space += +space_escape := %%%SPACE%%% +# +define config_filename +ifneq ($$(CONFIG_$(1)),"") +$(1)_FILENAME := $$(subst \\,\,$$(subst \$$(quote),$$(quote),$$(subst $$(space_escape),\$$(space),$$(patsubst "%",%,$$(subst $$(space),$$(space_escape),$$(CONFIG_$(1))))))) +ifneq ($$(patsubst /%,%,$$(firstword $$($(1)_FILENAME))),$$(firstword $$($(1)_FILENAME))) +else +ifeq ($$(wildcard $$($(1)_FILENAME)),) +ifneq ($$(wildcard $$(srctree)/$$($(1)_FILENAME)),) +$(1)_SRCPREFIX := $(srctree)/ +endif endif - -ifneq ($(wildcard $(obj)/.x509.list),) -ifneq ($(shell cat $(obj)/.x509.list),$(X509_CERTIFICATES)) -$(warning X.509 certificate list changed to "$(X509_CERTIFICATES)" from "$(shell cat $(obj)/.x509.list)") -$(shell rm $(obj)/.x509.list) endif endif +endef +# +############################################################################### + + +ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) + +$(eval $(call config_filename,SYSTEM_TRUSTED_KEYS)) + +SIGNING_X509-$(CONFIG_MODULE_SIG) += signing_key.x509 kernel/system_certificates.o: $(obj)/x509_certificate_list -quiet_cmd_x509certs = CERTS $@ - cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; $(kecho) " - Including cert $(X509)") +quiet_cmd_x509certs = CERTS $(SIGNING_X509-y) $(patsubst "%",%,$(2)) + cmd_x509certs = ( cat $(SIGNING_X509-y) /dev/null; \ + awk '/-----BEGIN CERTIFICATE-----/{flag=1;next}/-----END CERTIFICATE-----/{flag=0}flag' $(2) /dev/null | base64 -d ) > $@ || ( rm $@; exit 1) targets += $(obj)/x509_certificate_list -$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list - $(call if_changed,x509certs) +$(obj)/x509_certificate_list: $(SIGNING_X509-y) include/config/system/trusted/keys.h $(wildcard include/config/module/sig.h) $(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(SYSTEM_TRUSTED_KEYS_FILENAME) + $(call if_changed,x509certs,$(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(CONFIG_SYSTEM_TRUSTED_KEYS)) -targets += $(obj)/.x509.list -$(obj)/.x509.list: - @echo $(X509_CERTIFICATES) >$@ endif clean-files := x509_certificate_list .x509.list @@ -212,40 +241,16 @@ x509.genkey: @echo >>x509.genkey "authorityKeyIdentifier=keyid" endif -# We need to obtain the certificate from CONFIG_MODULE_SIG_KEY. -quiet_cmd_extract_der = CERT_DER $(2) - cmd_extract_der = scripts/extract-cert "$(2)" signing_key.x509 +$(eval $(call config_filename,MODULE_SIG_KEY)) -# CONFIG_MODULE_SIG_KEY is either a PKCS#11 URI or a filename. It is -# surrounded by quotes, and may contain spaces. To strip the quotes -# with $(patsubst) we need to turn the spaces into something else. -# And if it's a filename, those spaces need to be escaped as '\ ' in -# order to use it in dependencies or $(wildcard). -space := -space += -space_escape := %%%SPACE%%% -X509_SOURCE_temp := $(subst $(space),$(space_escape),$(CONFIG_MODULE_SIG_KEY)) -# We need this to check for absolute paths or PKCS#11 URIs. -X509_SOURCE_ONEWORD := $(patsubst "%",%,$(X509_SOURCE_temp)) -# This is the actual source filename/URI without the quotes -X509_SOURCE := $(subst $(space_escape),$(space),$(X509_SOURCE_ONEWORD)) -# This\ version\ with\ spaces\ escaped\ for\ $(wildcard)\ and\ dependencies -X509_SOURCE_ESCAPED := $(subst $(space_escape),\$(space),$(X509_SOURCE_ONEWORD)) - -ifeq ($(patsubst pkcs11:%,%,$(X509_SOURCE_ONEWORD)),$(X509_SOURCE_ONEWORD)) -# If it's a filename, depend on it. -X509_DEP := $(X509_SOURCE_ESCAPED) -ifeq ($(patsubst /%,%,$(X509_SOURCE_ONEWORD)),$(X509_SOURCE_ONEWORD)) -ifeq ($(wildcard $(X509_SOURCE_ESCAPED)),) -ifneq ($(wildcard $(srctree)/$(X509_SOURCE_ESCAPED)),) -# Non-absolute filename, found in source tree and not build tree -X509_SOURCE := $(srctree)/$(X509_SOURCE) -X509_DEP := $(srctree)/$(X509_SOURCE_ESCAPED) -endif -endif -endif +# If CONFIG_MODULE_SIG_KEY isn't a PKCS#11 URI, depend on it +ifeq ($(patsubst pkcs11:%,%,$(firstword $(MODULE_SIG_KEY_FILENAME))),$(firstword $(MODULE_SIG_KEY_FILENAME))) +X509_DEP := $(MODULE_SIG_KEY_SRCPREFIX)$(MODULE_SIG_KEY_FILENAME) endif +quiet_cmd_extract_der = SIGNING_CERT $(patsubst "%",%,$(2)) + cmd_extract_der = scripts/extract-cert $(2) signing_key.x509 + signing_key.x509: scripts/extract-cert include/config/module/sig/key.h $(X509_DEP) - $(call cmd,extract_der,$(X509_SOURCE)) + $(call cmd,extract_der,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY)) endif -- cgit v1.1