mailarchive of the ptxdist mailing list
 help / color / mirror / Atom feed
* [ptxdist] [PATCH v1 1/5] ptxd_make_world_common: make the package name available to scripts
@ 2021-08-04 14:23 Roland Hieber
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 2/5] libptxdist: introduce ptxd_exec_silent_stderr Roland Hieber
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Roland Hieber @ 2021-08-04 14:23 UTC (permalink / raw)
  To: ptxdist; +Cc: Roland Hieber

Variables named ${pkg} are already widely used throughout the code base
for different purposes, so name it ${pkg_name} instead.

Signed-off-by: Roland Hieber <rhi@pengutronix.de>
---
Turned out I didn't need it for this series, but I still think it's
useful in general.
---
 rules/post/ptxd_make_world_common.make | 1 +
 1 file changed, 1 insertion(+)

diff --git a/rules/post/ptxd_make_world_common.make b/rules/post/ptxd_make_world_common.make
index e5cf50214e9c..c9d22c6884a3 100644
--- a/rules/post/ptxd_make_world_common.make
+++ b/rules/post/ptxd_make_world_common.make
@@ -69,6 +69,7 @@ world/env/impl = \
 	pkg_makefile="$(call ptx/escape,$($(1)_MAKEFILE))"			\
 	pkg_infile="$(call ptx/escape,$($(1)_INFILE))"				\
 										\
+	pkg_name="$(call ptx/escape,$(PTX_MAP_TO_package_$(1)))"                \
 	pkg_pkg="$(call ptx/escape,$($(1)))"					\
 	pkg_version="$(call ptx/escape,$($(1)_VERSION))"			\
 	pkg_config="$(call ptx/escape,$($(1)_CONFIG))"				\
-- 
2.30.2


_______________________________________________
ptxdist mailing list
ptxdist@pengutronix.de
To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ptxdist] [PATCH v1 2/5] libptxdist: introduce ptxd_exec_silent_stderr
  2021-08-04 14:23 [ptxdist] [PATCH v1 1/5] ptxd_make_world_common: make the package name available to scripts Roland Hieber
@ 2021-08-04 14:23 ` Roland Hieber
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 3/5] ptxd_lib_code_signing: refactor hard-coded SoftHSM PIN in PKCS11 URIs Roland Hieber
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Roland Hieber @ 2021-08-04 14:23 UTC (permalink / raw)
  To: ptxdist; +Cc: Roland Hieber

Some programs  print stuff to stderr that are not errors and are
therefore not relevant to the usual build runs (e.g. openssl when
loading the PKCS#11 libraries), but they may still be useful for
debugging. When called with ptxd_exec_silent_stderr, stderr won't make
it to the terminal except with 'ptxdist -v', but the messages are still
available in the logfile.

Signed-off-by: Roland Hieber <rhi@pengutronix.de>
---
 scripts/libptxdist.sh | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/scripts/libptxdist.sh b/scripts/libptxdist.sh
index ee0ba39d3ea3..bb508798cb6f 100644
--- a/scripts/libptxdist.sh
+++ b/scripts/libptxdist.sh
@@ -776,6 +776,24 @@ ptxd_exec() {
 }
 export -f ptxd_exec
 
+#
+# execute command with silenced stderr, except when verbose building is enabled.
+# the stderr output of the command will always be written to the logfile.
+#
+ptxd_exec_silent_stderr() {
+	exec 8>&2
+	if [ "${PTXDIST_VERBOSE}" == "1" ]; then
+		:
+	elif [ -n "${PTXDIST_FD_LOGFILE}" ]; then
+		exec 2>&9
+	else
+		exec 2>/dev/null
+	fi
+	"${@}"
+	exec 2>&8 8>&-
+}
+export -f ptxd_exec_silent_stderr
+
 #
 # check if a previously executed pipe returned an error
 #
-- 
2.30.2


_______________________________________________
ptxdist mailing list
ptxdist@pengutronix.de
To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ptxdist] [PATCH v1 3/5] ptxd_lib_code_signing: refactor hard-coded SoftHSM PIN in PKCS11 URIs
  2021-08-04 14:23 [ptxdist] [PATCH v1 1/5] ptxd_make_world_common: make the package name available to scripts Roland Hieber
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 2/5] libptxdist: introduce ptxd_exec_silent_stderr Roland Hieber
@ 2021-08-04 14:23 ` Roland Hieber
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 4/5] ptxd_lib_code_signing: provide consumer functions with some environment Roland Hieber
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 5/5] ptxd_lib_code_signing: add key whitelist checks Roland Hieber
  3 siblings, 0 replies; 7+ messages in thread
From: Roland Hieber @ 2021-08-04 14:23 UTC (permalink / raw)
  To: ptxdist; +Cc: Roland Hieber

We'll need this type of function more often later.

Signed-off-by: Roland Hieber <rhi@pengutronix.de>
---
 scripts/lib/ptxd_lib_code_signing.sh | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/scripts/lib/ptxd_lib_code_signing.sh b/scripts/lib/ptxd_lib_code_signing.sh
index 5ba1a4666af4..66a2cab81395 100644
--- a/scripts/lib/ptxd_lib_code_signing.sh
+++ b/scripts/lib/ptxd_lib_code_signing.sh
@@ -49,6 +49,17 @@ softhsm_pkcs11_tool() {
 }
 export -f softhsm_pkcs11_tool
 
+#
+# softhsm_pkcs11_uri <uri>
+#
+# Add the SoftHSM PIN to the given URI.
+#
+softhsm_pkcs11_uri() {
+    local role="$1"
+    printf "pkcs11:token=%s;object=%s;pin-value=1111\n" "${keyprovider}" "${role}"
+}
+export -f softhsm_pkcs11_uri
+
 #
 # cs_init_variables
 #
@@ -95,7 +106,8 @@ cs_define_role() {
 
     mkdir -p "${keydir}/${role}" &&
     # default for SoftHSM
-    cs_set_uri "${role}" "pkcs11:token=${keyprovider};object=${role};pin-value=1111"
+    local uri=$(softhsm_pkcs11_uri "${role}")
+    cs_set_uri "${role}" "${uri}"
 }
 export -f cs_define_role
 
-- 
2.30.2


_______________________________________________
ptxdist mailing list
ptxdist@pengutronix.de
To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ptxdist] [PATCH v1 4/5] ptxd_lib_code_signing: provide consumer functions with some environment
  2021-08-04 14:23 [ptxdist] [PATCH v1 1/5] ptxd_make_world_common: make the package name available to scripts Roland Hieber
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 2/5] libptxdist: introduce ptxd_exec_silent_stderr Roland Hieber
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 3/5] ptxd_lib_code_signing: refactor hard-coded SoftHSM PIN in PKCS11 URIs Roland Hieber
@ 2021-08-04 14:23 ` Roland Hieber
  2021-08-04 15:23   ` Michael Olbrich
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 5/5] ptxd_lib_code_signing: add key whitelist checks Roland Hieber
  3 siblings, 1 reply; 7+ messages in thread
From: Roland Hieber @ 2021-08-04 14:23 UTC (permalink / raw)
  To: ptxdist; +Cc: Roland Hieber

The code signing consumer functions should be able to retrieve some
information about the recipe in which they were called in order to make
additional checks if needed. Refactor the (shell cs_get_*, …) calls into
macro calls of the form $(call ptx/cs-get-*, <PKG>, …). Let these
macros look up the package name (for now) from PTX_MAP_TO_package_<PKG>
before passing it to the shell functions. Using $(call world/env) here
would be practical, but would also cause make to complain about
recursive variable dependencies. Therefore variables must be added
to ptx/cs-consumer-env manually, but additional information can be added
later if needed.

Refactor the existing consumers in the code base too, and add an error
message in case anyone else that still uses the old API.

Signed-off-by: Roland Hieber <rhi@pengutronix.de>
---
 doc/dev_code_signing.rst                      |  2 +-
 doc/ref_code_signing_helpers.rst              | 25 ++++++-----
 rules/barebox.make                            |  2 +-
 rules/image-rauc.make                         |  6 +--
 rules/kernel.make                             |  6 +--
 rules/pre/030-code-signing-consumers.make     | 41 +++++++++++++++++++
 rules/rauc.make                               |  2 +-
 .../templates/template-barebox-imx-habv4-make |  6 +--
 scripts/lib/ptxd_lib_code_signing.sh          | 13 ++++++
 9 files changed, 80 insertions(+), 23 deletions(-)
 create mode 100644 rules/pre/030-code-signing-consumers.make

diff --git a/doc/dev_code_signing.rst b/doc/dev_code_signing.rst
index b9a7c42f2a55..413f694980eb 100644
--- a/doc/dev_code_signing.rst
+++ b/doc/dev_code_signing.rst
@@ -164,7 +164,7 @@ also via an environment variable.
 .. code-block:: none
 
     $(call install_copy, rauc, 0, 0, 0644, \
-      $(shell cs_get_ca update), \
+      $(call ptx/cs-get-ca, RAUC, update), \
       /etc/rauc/ca.cert.pem)
 
 .. note:: When code signing helper functions are used in make variables (e.g.
diff --git a/doc/ref_code_signing_helpers.rst b/doc/ref_code_signing_helpers.rst
index fd16ca763557..d3429778d94d 100644
--- a/doc/ref_code_signing_helpers.rst
+++ b/doc/ref_code_signing_helpers.rst
@@ -297,19 +297,21 @@ In the example given in :ref:`cs_group_add_roles` above, this would print::
 Consumer Functions
 ~~~~~~~~~~~~~~~~~~
 
+The consumer functions are implemented as make macros.
 Packages that want to sign something or need access to keys/CAs can retrieve
 PKCS#11 URIs and CA keyrings with these helpers.
 
+.. _ptx/cs-get-uri:
 .. _cs_get_uri:
 
-cs_get_uri
-^^^^^^^^^^
+ptx/cs-get-uri
+^^^^^^^^^^^^^^
 
 Usage:
 
-.. code-block:: bash
+.. code-block:: make
 
-    cs_get_uri <role>
+    $(call ptx/cs-get-uri, <PKG>, <role>)
 
 Get PKCS#11 URI for role.
 
@@ -317,16 +319,17 @@ Preconditions:
 
 - the URI must have been set (see :ref:`cs_set_uri`)
 
+.. _ptx/cs-get-ca:
 .. _cs_get_ca:
 
-cs_get_ca
-^^^^^^^^^
+ptx/cs-get-ca
+^^^^^^^^^^^^^
 
 Usage:
 
-.. code-block:: bash
+.. code-block:: make
 
-    cs_get_ca <role>
+    $(call ptx/cs-get-ca, <PKG>, <role>)
 
 Get path to the CA keyring in PEM format for role.
 
@@ -347,7 +350,7 @@ Example:
 
    # set up kernel module signing, and add a trusted CA if the provider set one
    KERNEL_SIGN_OPT =
-   	CONFIG_MODULE_SIG_KEY='"$(shell cs_get_uri kernel-modules)"' \
+   	CONFIG_MODULE_SIG_KEY='"$(call ptx/cs-get-uri, KERNEL, kernel-modules)"' \
    	CONFIG_MODULE_SIG_ALL=y \
-   	$(if $(shell cs_get_ca kernel-trusted), \
-   		CONFIG_SYSTEM_TRUSTED_KEYS=$(shell cs_get_ca kernel-trusted))
+   	$(if $(call ptx/cs-get-ca, KERNEL, kernel-trusted), \
+   		CONFIG_SYSTEM_TRUSTED_KEYS=$(call ptx/cs-get-ca, KERNEL, kernel-trusted))
diff --git a/rules/barebox.make b/rules/barebox.make
index bea9f3adcbf8..983d34032e0d 100644
--- a/rules/barebox.make
+++ b/rules/barebox.make
@@ -103,7 +103,7 @@ endif
 ifdef PTXCONF_CODE_SIGNING
 BAREBOX_MAKE_ENV = \
 	$(CODE_SIGNING_ENV) \
-	IMAGE_KERNEL_FIT_KEY="$(shell cs_get_uri image-kernel-fit)"
+	IMAGE_KERNEL_FIT_KEY="$(call ptx/cs-get-uri, BAREBOX, image-kernel-fit)"
 endif
 
 $(STATEDIR)/barebox.compile:
diff --git a/rules/image-rauc.make b/rules/image-rauc.make
index fe1b0e89be7c..c8747231f8f1 100644
--- a/rules/image-rauc.make
+++ b/rules/image-rauc.make
@@ -32,9 +32,9 @@ IMAGE_RAUC_ENV	= \
 	RAUC_BUNDLE_VERSION="$(call remove_quotes, $(PTXCONF_RAUC_BUNDLE_VERSION))" \
 	RAUC_BUNDLE_BUILD=$(call ptx/sh, date +%FT%T%z) \
 	RAUC_BUNDLE_DESCRIPTION=$(PTXCONF_IMAGE_RAUC_DESCRIPTION) \
-	RAUC_KEY="$(shell cs_get_uri update)" \
-	RAUC_CERT="$(shell cs_get_uri update)" \
-	RAUC_KEYRING="$(shell cs_get_ca update)"
+	RAUC_KEY="$(call ptx/cs-get-uri, IMAGE_RAUC, update)" \
+	RAUC_CERT="$(call ptx/cs-get-uri, IMAGE_RAUC, update)" \
+	RAUC_KEYRING="$(call ptx/cs-get-ca, IMAGE_RAUC, update)"
 
 $(IMAGE_RAUC_IMAGE):
 	@$(call targetinfo)
diff --git a/rules/kernel.make b/rules/kernel.make
index 9caff677918e..e6faba82df38 100644
--- a/rules/kernel.make
+++ b/rules/kernel.make
@@ -73,12 +73,12 @@ KERNEL_BASE_OPT		= \
 
 ifdef PTXCONF_KERNEL_CODE_SIGNING
 KERNEL_BASE_OPT		+= \
-	$(if $(shell cs_get_ca kernel-trusted), \
-		CONFIG_SYSTEM_TRUSTED_KEYS=$(shell cs_get_ca kernel-trusted))
+	$(if $(call ptx/cs-get-ca, KERNEL, kernel-trusted), \
+		CONFIG_SYSTEM_TRUSTED_KEYS=$(call ptx/cs-get-ca, KERNEL, kernel-trusted))
 endif
 ifdef PTXCONF_KERNEL_MODULES_SIGN
 KERNEL_BASE_OPT		+= \
-	CONFIG_MODULE_SIG_KEY='"$(shell cs_get_uri kernel-modules)"'
+	CONFIG_MODULE_SIG_KEY='"$(call ptx/cs-get-uri, KERNEL, kernel-modules)"'
 endif
 
 # Intermediate option. This will be used by kernel module packages.
diff --git a/rules/pre/030-code-signing-consumers.make b/rules/pre/030-code-signing-consumers.make
new file mode 100644
index 000000000000..72ee8e63b7b9
--- /dev/null
+++ b/rules/pre/030-code-signing-consumers.make
@@ -0,0 +1,41 @@
+# -*-makefile-*-
+#
+# Copyright (C) 2021 Roland Hieber, Pengutronix <rhi@pengutronix.de>
+#
+# For further information about the PTXdist project and license conditions
+# see the README file.
+#
+#
+
+#
+# Usage: $(call ptx/cs-consumer-env, <PKG>)
+#
+# We usually want to use cs-get-* macros inside a <PKG>_MAKE_OPT etc., which is
+# referenced in world/env, so we cannot use world/env to set pkg_name without
+# running into circular variable dependencies.
+#
+ptx/cs-consumer-env = \
+	pkg_name='$(PTX_MAP_TO_package_$(strip $(1)))' \
+	$(CODE_SIGNING_ENV)
+
+#
+# Usage: $(call ptx/cs-get-uri, <PKG>, <role>)
+#
+ptx/cs-get-uri = \
+	$(strip \
+		$(shell \
+			$(call ptx/cs-consumer-env, $(1))\
+				cs_get_uri '$(strip $(2))'\
+		)\
+	)
+
+#
+# Usage: $(call ptx/cs-get-ca, <PKG>, <role>)
+#
+ptx/cs-get-ca = \
+	$(strip \
+		$(shell \
+			$(call ptx/cs-consumer-env, $(1))\
+				cs_get_ca '$(strip $(2))'\
+		)\
+	)
diff --git a/rules/rauc.make b/rules/rauc.make
index 08df6336a7cd..3c28befcd3ff 100644
--- a/rules/rauc.make
+++ b/rules/rauc.make
@@ -78,7 +78,7 @@ ifdef PTXCONF_RAUC_CONFIGURATION
 	@$(call install_replace, rauc, /etc/rauc/system.conf, \
 		@RAUC_BUNDLE_COMPATIBLE@, \
 		"$(call remove_quotes,$(PTXCONF_RAUC_COMPATIBLE))")
-	@$(call install_copy, rauc, 0, 0, 0644, $(shell cs_get_ca update), \
+	@$(call install_copy, rauc, 0, 0, 0644, $(call ptx/cs-get-ca, RAUC, update), \
 		/etc/rauc/ca.cert.pem)
 endif
 
diff --git a/rules/templates/template-barebox-imx-habv4-make b/rules/templates/template-barebox-imx-habv4-make
index cc825dc90292..b2d5d7100fc9 100644
--- a/rules/templates/template-barebox-imx-habv4-make
+++ b/rules/templates/template-barebox-imx-habv4-make
@@ -64,9 +64,9 @@ endif
 
 BAREBOX_@PACKAGE@_MAKE_ENV	= \
 	$(CODE_SIGNING_ENV) \
-	CSF="$(shell cs_get_uri imx-habv4-csf1)" \
-	IMG="$(shell cs_get_uri imx-habv4-img1)" \
-	FIT_KEY="$(shell cs_get_uri image-kernel-fit)"
+	CSF="$(call ptx/cs-get-uri, BAREBOX_@PACKAGE@, imx-habv4-csf1)" \
+	IMG="$(call ptx/cs-get-uri, BAREBOX_@PACKAGE@, imx-habv4-img1)" \
+	FIT_KEY="$(call ptx/cs-get-uri, BAREBOX_@PACKAGE@, image-kernel-fit)"
 
 BAREBOX_@PACKAGE@_MAKE_OPT	:= $(BAREBOX_@PACKAGE@_CONF_OPT)
 
diff --git a/scripts/lib/ptxd_lib_code_signing.sh b/scripts/lib/ptxd_lib_code_signing.sh
index 66a2cab81395..24730d3cf742 100644
--- a/scripts/lib/ptxd_lib_code_signing.sh
+++ b/scripts/lib/ptxd_lib_code_signing.sh
@@ -1,6 +1,7 @@
 #!/bin/bash
 #
 # Copyright (C) 2019 Sascha Hauer <s.hauer@pengutronix.de>
+# Copyright (C) 2021 Roland Hieber, Pengutronix <rhi@pengutronix.de>
 #
 # For further information about the PTXdist project and license conditions
 # see the README file.
@@ -176,6 +177,12 @@ export -f cs_set_uri
 # Get the uri from a role
 #
 cs_get_uri() {
+    if [ -z "${pkg_name}" ]; then
+	    echo ERROR_UNSUPPORTED_CS_API_CALL
+	    ptxd_bailout '$(shell cs_get_uri, <role>) is no longer supported in make files.' \
+		'Use $(call ptx/cs-get-uri, <PKG>, <role>) instead.'
+    fi
+
     local role="${1}"
     cs_init_variables
 
@@ -297,6 +304,12 @@ export -f cs_import_key_from_pem
 # Get the path to the CA in pem format from a role
 #
 cs_get_ca() {
+    if [ -z "${pkg_name}" ]; then
+	    echo ERROR_UNSUPPORTED_CS_API_CALL
+	    ptxd_bailout '$(shell cs_get_ca, …) is no longer supported in make files.' \
+		'Use $(call ptx/cs-get-ca, <PKG>, …) instead.'
+    fi
+
     local role="${1}"
     cs_init_variables
 
-- 
2.30.2


_______________________________________________
ptxdist mailing list
ptxdist@pengutronix.de
To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ptxdist] [PATCH v1 5/5] ptxd_lib_code_signing: add key whitelist checks
  2021-08-04 14:23 [ptxdist] [PATCH v1 1/5] ptxd_make_world_common: make the package name available to scripts Roland Hieber
                   ` (2 preceding siblings ...)
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 4/5] ptxd_lib_code_signing: provide consumer functions with some environment Roland Hieber
@ 2021-08-04 14:23 ` Roland Hieber
  2021-08-04 15:58   ` Michael Olbrich
  3 siblings, 1 reply; 7+ messages in thread
From: Roland Hieber @ 2021-08-04 14:23 UTC (permalink / raw)
  To: ptxdist; +Cc: Roland Hieber

Signed-off-by: Roland Hieber <rhi@pengutronix.de>
---
 doc/dev_code_signing.rst                  | 68 +++++++++++++++++++++++
 platforms/code-signing.in                 | 22 ++++++++
 rules/pre/030-code-signing-consumers.make |  6 ++
 scripts/lib/ptxd_lib_code_signing.sh      | 52 ++++++++++++++++-
 4 files changed, 147 insertions(+), 1 deletion(-)

diff --git a/doc/dev_code_signing.rst b/doc/dev_code_signing.rst
index 413f694980eb..aaaaae0d9107 100644
--- a/doc/dev_code_signing.rst
+++ b/doc/dev_code_signing.rst
@@ -172,3 +172,71 @@ also via an environment variable.
   (``=``, not ``:=``).
   Otherwise the variable is expanded before a code signing provider can perform
   its setup.
+
+Key Whitelisting
+~~~~~~~~~~~~~~~~
+
+In some use cases, it may be feasible to do additional checks to make sure that
+a package uses the correct key material.
+For example, suppose you have a "development" code signing provider (e.g. with a
+SoftHSM workflow) which you use to sign your development kernels,
+and a "release" provider (e.g. on a HSM) which you use to sign your release kernels,
+and a "development" and "release" variant of the bootloader which only boots
+kernels that have been signed with the respective development or release key.
+Now you might want to prevent the "release" bootloader from accidentally being
+provided with the key for the "development" kernel –
+otherwise someone could boot a development kernel on an actual production
+board, and use the additional debugging features of the kernel to do things
+with it that it was not meant to do.
+
+When the ``CODE_SIGNING_REQUIRE_WHITELIST`` kconfig symbol is enabled,
+the consumer functions :ref:`ptx/cs-get-ca` and :ref:`ptx/cs-get-uri`
+look up the triplet of package name, role name, and the pubkey's SHA256
+fingerprint in a whitelist, whose file name is determined by the
+``CODE_SIGNING_WHITELIST_FILENAME`` kconfig symbol (the default path is
+``configs/platform-<name>/code-signing-whitelist``).
+If a key or a CA is not whitelisted for the package in which it is to be used,
+the functions will exit with an error message on the terminal::
+
+   $ ptxdist -v print KERNEL_MAKE_OPT
+   ptxdist: error: SPKI whitelist record 'kernel kernel-modules
+   69C9BBB8BB4DFAE74AB21D06DFB5F2C67066373AE545453276847340822CDF04' not found in
+   distrokit/configs/platform-v7a/code-signing-whitelist
+
+   …/ptxdist/rules/kernel.make:196: *** cs-get-uri: whitelist check failed, see errors above.  Stop.
+
+
+If ``CODE_SIGNING_REQUIRE_WHITELIST`` is disabled (the default),
+all keys and CAs are provided to all packages without further checks.
+
+The format of the code signing whitelist consists of one triplet per line, in
+which the elements of the triplet are separated by whitespace.
+If a CA is to be checked, the role name is prefixed with a literal ``ca:``.
+All other unmatched lines in the file are ignored, but we suggest to use ``#``
+to start a line comment so as not to add a whitelist record accidentally.
+
+For example, here is a whitelist for use with the *devel* code provider which
+allows all provided keys to be used by their respective consumers::
+
+   # format: package-name role-name sha256-pubkey-fingerprint
+   kernel      kernel-modules 69C9BBB8BB4DFAE74AB21D06DFB5F2C67066373AE545453276847340822CDF04
+   image-rauc  update         0034F8FE5ADC3B0DFE642407275D144DE2398C68CC9A86DD6703D7151116B44E
+   image-rauc  ca:update      0034F8FE5ADC3B0DFE642407275D144DE2398C68CC9A86DD6703D7151116B44E
+   rauc        ca:update      0034F8FE5ADC3B0DFE642407275D144DE2398C68CC9A86DD6703D7151116B44E
+
+.. note:: The match is case-sensitive, and the fingerprints are expected
+   in uppercase.
+
+   If a CA consists of more than one certificate, all of their fingerprints
+   must be whitelisted.
+
+You can determine the key fingerprints by copying it from the error message,
+or with the `spki-hash`__ tool from the ``host-extract-cert`` package,
+or with openssl::
+
+   $ openssl pkey -in keyfile.pem -pubout -outform der \
+     | openssl sha256 \
+     | tr 'a-z' 'A-Z'
+   (STDIN)= 69C9BBB8BB4DFAE74AB21D06DFB5F2C67066373AE545453276847340822CDF04
+
+__ https://git.pengutronix.de/cgit/extract-cert/tree/spki-hash.c
diff --git a/platforms/code-signing.in b/platforms/code-signing.in
index 81f9ef6f3c9e..92f555c7e965 100644
--- a/platforms/code-signing.in
+++ b/platforms/code-signing.in
@@ -20,4 +20,26 @@ source "generated/code_signing_provider.in"
 
 endchoice
 
+config CODE_SIGNING_REQUIRE_WHITELISTED_KEYS
+	bool
+	prompt "require whitelisted keys"
+	help
+	  Every time a key from the code provider is used, check if the consumer
+	  is allowed to use it.
+
+	  Code signing consumers can depend on this option if they want to force
+	  the key whitelist check.
+
+if CODE_SIGNING_REQUIRE_WHITELISTED_KEYS
+
+config CODE_SIGNING_WHITELIST_FILENAME
+	string
+	prompt "whitelist file name"
+	default "code-signing-whitelist"
+	help
+	  This file name is used for the key whitelist. The path is relative to
+	  PTXDIST_PLATFORMCONFIGDIR (e.g. configs/platform-nnn/).
+
+endif # CODE_SIGNING_REQUIRE_WHITELISTED_KEYS
+
 endif
diff --git a/rules/pre/030-code-signing-consumers.make b/rules/pre/030-code-signing-consumers.make
index 72ee8e63b7b9..439db626dd14 100644
--- a/rules/pre/030-code-signing-consumers.make
+++ b/rules/pre/030-code-signing-consumers.make
@@ -27,6 +27,9 @@ ptx/cs-get-uri = \
 			$(call ptx/cs-consumer-env, $(1))\
 				cs_get_uri '$(strip $(2))'\
 		)\
+		$(if $(filter-out 0,$(.SHELLSTATUS)),\
+			$(error cs-get-uri: whitelist check failed, see errors above)\
+		)\
 	)
 
 #
@@ -38,4 +41,7 @@ ptx/cs-get-ca = \
 			$(call ptx/cs-consumer-env, $(1))\
 				cs_get_ca '$(strip $(2))'\
 		)\
+		$(if $(filter-out 0,$(.SHELLSTATUS)),\
+			$(error cs-get-ca: whitelist check failed, see errors above)\
+		)\
 	)
diff --git a/scripts/lib/ptxd_lib_code_signing.sh b/scripts/lib/ptxd_lib_code_signing.sh
index 24730d3cf742..332bab22e7c8 100644
--- a/scripts/lib/ptxd_lib_code_signing.sh
+++ b/scripts/lib/ptxd_lib_code_signing.sh
@@ -1,6 +1,7 @@
 #!/bin/bash
 #
 # Copyright (C) 2019 Sascha Hauer <s.hauer@pengutronix.de>
+# Copyright (C) 2020 Jan Luebbe <j.luebbe@pengutronix.de>
 # Copyright (C) 2021 Roland Hieber, Pengutronix <rhi@pengutronix.de>
 #
 # For further information about the PTXdist project and license conditions
@@ -70,6 +71,7 @@ cs_init_variables() {
     sysroot="$(ptxd_get_ptxconf PTXCONF_SYSROOT_HOST)"
     keyprovider="$(ptxd_get_ptxconf PTXCONF_CODE_SIGNING_PROVIDER)"
     keydir="${sysroot}/var/lib/keys/${keyprovider}"
+    whitelist="$(ptxd_get_ptxconf PTXCONF_CODE_SIGNING_WHITELIST_FILENAME || true)"
 }
 export -f cs_init_variables
 
@@ -157,6 +159,40 @@ cs_group_get_roles() {
 }
 export -f cs_group_get_roles
 
+#
+# cs_check_whitelisted <role> <uri/pem or fingerprint prefixed with "sha256:">
+#
+# Checks if the SPKI (Subject Public Key Info) Hash is in the whitelist
+#
+cs_check_whitelisted() {
+    local role="${1:-ERROR_ROLE_IS_EMPTY}"
+    local src="${2}"
+
+    if [ "$(ptxd_get_ptxconf PTXCONF_CODE_SIGNING_REQUIRE_WHITELISTED_KEYS)" != "y" ]; then
+	return
+    fi
+
+    if ! ptxd_in_path PTXDIST_PATH_PLATFORMCONFIGDIR "${whitelist}"; then
+	ptxd_bailout "${pkg_name}: SPKI hash whitelist check for ${role} (${src}) is required, but configs/<platform>/${whitelist} is missing."
+    fi
+    local whitelist_path="${ptxd_reply}"
+
+    local hash
+    if [ "${src#sha256:}" != "${src}" ]; then
+	hash="${src#sha256:}"
+    else
+	hash=$(ptxd_exec_silent_stderr spki-hash "${src}")
+    fi
+    hash=${hash:-ERROR_HASH_IS_EMPTY}
+    needle="${pkg_name}\s\+${role}\s\+${hash}"
+
+    if ! grep -q --line-regexp "${needle}" "${whitelist_path}"; then
+	echo ERROR_KEY_NOT_WHITELISTED
+	ptxd_bailout "SPKI whitelist record '${pkg_name} ${role} ${hash}' not found in $(ptxd_print_path "${whitelist_path}")"
+    fi
+}
+export -f cs_check_whitelisted
+
 #
 # cs_set_uri <role> <uri>
 #
@@ -198,7 +234,12 @@ cs_get_uri() {
 	    return
 	fi
     fi
-    cat "${keydir}/${role}/uri"
+
+    local uri=$(cat "${keydir}/${role}/uri")
+    if [ -z "${cs_no_whitelist_check}" ]; then
+	cs_check_whitelisted "${role}" "${uri}"
+    fi
+    echo "${uri}"
 }
 export -f cs_get_uri
 
@@ -321,6 +362,9 @@ cs_get_ca() {
     fi
 
     if [ -e "${ca}" ]; then
+	while read fp; do
+	    cs_check_whitelisted "ca:${role}" "sha256:${fp}"
+	done < "${keydir}/${role}/ca.fingerprints"
 	echo "${ca}"
     fi
 }
@@ -339,6 +383,9 @@ cs_append_ca_from_pem() {
     cat "${pem}" >> "${keydir}/${role}/ca.pem"
     # add new line in case ${pem} does not end with an EOL
     echo >> "${keydir}/${role}/ca.pem"
+
+    openssl x509 -in "${pem}" -inform pem -noout -pubkey | \
+	spki-hash /dev/stdin >> "${keydir}/${role}/ca.fingerprints"
 }
 export -f cs_append_ca_from_pem
 
@@ -370,7 +417,10 @@ cs_append_ca_from_uri() {
     cs_init_variables
 
     if [ -z "${uri}" ]; then
+	# cs_append_ca_from_der will check this later
+	local cs_no_whitelist_check=1
 	uri=$(cs_get_uri "${role}")
+	unset cs_no_whitelist_check
     fi
 
     ptxd_exec extract-cert "${uri}" "${tmpdir}/ca.der" &&
-- 
2.30.2


_______________________________________________
ptxdist mailing list
ptxdist@pengutronix.de
To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ptxdist] [PATCH v1 4/5] ptxd_lib_code_signing: provide consumer functions with some environment
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 4/5] ptxd_lib_code_signing: provide consumer functions with some environment Roland Hieber
@ 2021-08-04 15:23   ` Michael Olbrich
  0 siblings, 0 replies; 7+ messages in thread
From: Michael Olbrich @ 2021-08-04 15:23 UTC (permalink / raw)
  To: Roland Hieber, ptxdist

On Wed, Aug 04, 2021 at 04:23:29PM +0200, Roland Hieber wrote:
> The code signing consumer functions should be able to retrieve some
> information about the recipe in which they were called in order to make
> additional checks if needed. Refactor the (shell cs_get_*, …) calls into
> macro calls of the form $(call ptx/cs-get-*, <PKG>, …). Let these
> macros look up the package name (for now) from PTX_MAP_TO_package_<PKG>
> before passing it to the shell functions. Using $(call world/env) here
> would be practical, but would also cause make to complain about
> recursive variable dependencies. Therefore variables must be added
> to ptx/cs-consumer-env manually, but additional information can be added
> later if needed.
> 
> Refactor the existing consumers in the code base too, and add an error
> message in case anyone else that still uses the old API.
> 
> Signed-off-by: Roland Hieber <rhi@pengutronix.de>
> ---
>  doc/dev_code_signing.rst                      |  2 +-
>  doc/ref_code_signing_helpers.rst              | 25 ++++++-----
>  rules/barebox.make                            |  2 +-
>  rules/image-rauc.make                         |  6 +--
>  rules/kernel.make                             |  6 +--
>  rules/pre/030-code-signing-consumers.make     | 41 +++++++++++++++++++
>  rules/rauc.make                               |  2 +-
>  .../templates/template-barebox-imx-habv4-make |  6 +--
>  scripts/lib/ptxd_lib_code_signing.sh          | 13 ++++++
>  9 files changed, 80 insertions(+), 23 deletions(-)
>  create mode 100644 rules/pre/030-code-signing-consumers.make
> 
> diff --git a/doc/dev_code_signing.rst b/doc/dev_code_signing.rst
> index b9a7c42f2a55..413f694980eb 100644
> --- a/doc/dev_code_signing.rst
> +++ b/doc/dev_code_signing.rst
> @@ -164,7 +164,7 @@ also via an environment variable.
>  .. code-block:: none
>  
>      $(call install_copy, rauc, 0, 0, 0644, \
> -      $(shell cs_get_ca update), \
> +      $(call ptx/cs-get-ca, RAUC, update), \
>        /etc/rauc/ca.cert.pem)
>  
>  .. note:: When code signing helper functions are used in make variables (e.g.
> diff --git a/doc/ref_code_signing_helpers.rst b/doc/ref_code_signing_helpers.rst
> index fd16ca763557..d3429778d94d 100644
> --- a/doc/ref_code_signing_helpers.rst
> +++ b/doc/ref_code_signing_helpers.rst
> @@ -297,19 +297,21 @@ In the example given in :ref:`cs_group_add_roles` above, this would print::
>  Consumer Functions
>  ~~~~~~~~~~~~~~~~~~
>  
> +The consumer functions are implemented as make macros.
>  Packages that want to sign something or need access to keys/CAs can retrieve
>  PKCS#11 URIs and CA keyrings with these helpers.
>  
> +.. _ptx/cs-get-uri:
>  .. _cs_get_uri:
>  
> -cs_get_uri
> -^^^^^^^^^^
> +ptx/cs-get-uri
> +^^^^^^^^^^^^^^
>  
>  Usage:
>  
> -.. code-block:: bash
> +.. code-block:: make
>  
> -    cs_get_uri <role>
> +    $(call ptx/cs-get-uri, <PKG>, <role>)
>  
>  Get PKCS#11 URI for role.
>  
> @@ -317,16 +319,17 @@ Preconditions:
>  
>  - the URI must have been set (see :ref:`cs_set_uri`)
>  
> +.. _ptx/cs-get-ca:
>  .. _cs_get_ca:
>  
> -cs_get_ca
> -^^^^^^^^^
> +ptx/cs-get-ca
> +^^^^^^^^^^^^^
>  
>  Usage:
>  
> -.. code-block:: bash
> +.. code-block:: make
>  
> -    cs_get_ca <role>
> +    $(call ptx/cs-get-ca, <PKG>, <role>)
>  
>  Get path to the CA keyring in PEM format for role.
>  
> @@ -347,7 +350,7 @@ Example:
>  
>     # set up kernel module signing, and add a trusted CA if the provider set one
>     KERNEL_SIGN_OPT =
> -   	CONFIG_MODULE_SIG_KEY='"$(shell cs_get_uri kernel-modules)"' \
> +   	CONFIG_MODULE_SIG_KEY='"$(call ptx/cs-get-uri, KERNEL, kernel-modules)"' \
>     	CONFIG_MODULE_SIG_ALL=y \
> -   	$(if $(shell cs_get_ca kernel-trusted), \
> -   		CONFIG_SYSTEM_TRUSTED_KEYS=$(shell cs_get_ca kernel-trusted))
> +   	$(if $(call ptx/cs-get-ca, KERNEL, kernel-trusted), \
> +   		CONFIG_SYSTEM_TRUSTED_KEYS=$(call ptx/cs-get-ca, KERNEL, kernel-trusted))
> diff --git a/rules/barebox.make b/rules/barebox.make
> index bea9f3adcbf8..983d34032e0d 100644
> --- a/rules/barebox.make
> +++ b/rules/barebox.make
> @@ -103,7 +103,7 @@ endif
>  ifdef PTXCONF_CODE_SIGNING
>  BAREBOX_MAKE_ENV = \
>  	$(CODE_SIGNING_ENV) \
> -	IMAGE_KERNEL_FIT_KEY="$(shell cs_get_uri image-kernel-fit)"
> +	IMAGE_KERNEL_FIT_KEY="$(call ptx/cs-get-uri, BAREBOX, image-kernel-fit)"
>  endif
>  
>  $(STATEDIR)/barebox.compile:
> diff --git a/rules/image-rauc.make b/rules/image-rauc.make
> index fe1b0e89be7c..c8747231f8f1 100644
> --- a/rules/image-rauc.make
> +++ b/rules/image-rauc.make
> @@ -32,9 +32,9 @@ IMAGE_RAUC_ENV	= \
>  	RAUC_BUNDLE_VERSION="$(call remove_quotes, $(PTXCONF_RAUC_BUNDLE_VERSION))" \
>  	RAUC_BUNDLE_BUILD=$(call ptx/sh, date +%FT%T%z) \
>  	RAUC_BUNDLE_DESCRIPTION=$(PTXCONF_IMAGE_RAUC_DESCRIPTION) \
> -	RAUC_KEY="$(shell cs_get_uri update)" \
> -	RAUC_CERT="$(shell cs_get_uri update)" \
> -	RAUC_KEYRING="$(shell cs_get_ca update)"
> +	RAUC_KEY="$(call ptx/cs-get-uri, IMAGE_RAUC, update)" \
> +	RAUC_CERT="$(call ptx/cs-get-uri, IMAGE_RAUC, update)" \
> +	RAUC_KEYRING="$(call ptx/cs-get-ca, IMAGE_RAUC, update)"
>  
>  $(IMAGE_RAUC_IMAGE):
>  	@$(call targetinfo)
> diff --git a/rules/kernel.make b/rules/kernel.make
> index 9caff677918e..e6faba82df38 100644
> --- a/rules/kernel.make
> +++ b/rules/kernel.make
> @@ -73,12 +73,12 @@ KERNEL_BASE_OPT		= \
>  
>  ifdef PTXCONF_KERNEL_CODE_SIGNING
>  KERNEL_BASE_OPT		+= \
> -	$(if $(shell cs_get_ca kernel-trusted), \
> -		CONFIG_SYSTEM_TRUSTED_KEYS=$(shell cs_get_ca kernel-trusted))
> +	$(if $(call ptx/cs-get-ca, KERNEL, kernel-trusted), \
> +		CONFIG_SYSTEM_TRUSTED_KEYS=$(call ptx/cs-get-ca, KERNEL, kernel-trusted))
>  endif
>  ifdef PTXCONF_KERNEL_MODULES_SIGN
>  KERNEL_BASE_OPT		+= \
> -	CONFIG_MODULE_SIG_KEY='"$(shell cs_get_uri kernel-modules)"'
> +	CONFIG_MODULE_SIG_KEY='"$(call ptx/cs-get-uri, KERNEL, kernel-modules)"'
>  endif
>  
>  # Intermediate option. This will be used by kernel module packages.
> diff --git a/rules/pre/030-code-signing-consumers.make b/rules/pre/030-code-signing-consumers.make
> new file mode 100644
> index 000000000000..72ee8e63b7b9
> --- /dev/null
> +++ b/rules/pre/030-code-signing-consumers.make
> @@ -0,0 +1,41 @@
> +# -*-makefile-*-
> +#
> +# Copyright (C) 2021 Roland Hieber, Pengutronix <rhi@pengutronix.de>
> +#
> +# For further information about the PTXdist project and license conditions
> +# see the README file.
> +#
> +#
> +
> +#
> +# Usage: $(call ptx/cs-consumer-env, <PKG>)
> +#
> +# We usually want to use cs-get-* macros inside a <PKG>_MAKE_OPT etc., which is
> +# referenced in world/env, so we cannot use world/env to set pkg_name without
> +# running into circular variable dependencies.
> +#
> +ptx/cs-consumer-env = \
> +	pkg_name='$(PTX_MAP_TO_package_$(strip $(1)))' \
> +	$(CODE_SIGNING_ENV)
> +
> +#
> +# Usage: $(call ptx/cs-get-uri, <PKG>, <role>)
> +#
> +ptx/cs-get-uri = \

Use 'define' for multi-line macros. There are several examples in
rules/pre.

Michael

> +	$(strip \
> +		$(shell \
> +			$(call ptx/cs-consumer-env, $(1))\
> +				cs_get_uri '$(strip $(2))'\
> +		)\
> +	)
> +
> +#
> +# Usage: $(call ptx/cs-get-ca, <PKG>, <role>)
> +#
> +ptx/cs-get-ca = \
> +	$(strip \
> +		$(shell \
> +			$(call ptx/cs-consumer-env, $(1))\
> +				cs_get_ca '$(strip $(2))'\
> +		)\
> +	)
> diff --git a/rules/rauc.make b/rules/rauc.make
> index 08df6336a7cd..3c28befcd3ff 100644
> --- a/rules/rauc.make
> +++ b/rules/rauc.make
> @@ -78,7 +78,7 @@ ifdef PTXCONF_RAUC_CONFIGURATION
>  	@$(call install_replace, rauc, /etc/rauc/system.conf, \
>  		@RAUC_BUNDLE_COMPATIBLE@, \
>  		"$(call remove_quotes,$(PTXCONF_RAUC_COMPATIBLE))")
> -	@$(call install_copy, rauc, 0, 0, 0644, $(shell cs_get_ca update), \
> +	@$(call install_copy, rauc, 0, 0, 0644, $(call ptx/cs-get-ca, RAUC, update), \
>  		/etc/rauc/ca.cert.pem)
>  endif
>  
> diff --git a/rules/templates/template-barebox-imx-habv4-make b/rules/templates/template-barebox-imx-habv4-make
> index cc825dc90292..b2d5d7100fc9 100644
> --- a/rules/templates/template-barebox-imx-habv4-make
> +++ b/rules/templates/template-barebox-imx-habv4-make
> @@ -64,9 +64,9 @@ endif
>  
>  BAREBOX_@PACKAGE@_MAKE_ENV	= \
>  	$(CODE_SIGNING_ENV) \
> -	CSF="$(shell cs_get_uri imx-habv4-csf1)" \
> -	IMG="$(shell cs_get_uri imx-habv4-img1)" \
> -	FIT_KEY="$(shell cs_get_uri image-kernel-fit)"
> +	CSF="$(call ptx/cs-get-uri, BAREBOX_@PACKAGE@, imx-habv4-csf1)" \
> +	IMG="$(call ptx/cs-get-uri, BAREBOX_@PACKAGE@, imx-habv4-img1)" \
> +	FIT_KEY="$(call ptx/cs-get-uri, BAREBOX_@PACKAGE@, image-kernel-fit)"
>  
>  BAREBOX_@PACKAGE@_MAKE_OPT	:= $(BAREBOX_@PACKAGE@_CONF_OPT)
>  
> diff --git a/scripts/lib/ptxd_lib_code_signing.sh b/scripts/lib/ptxd_lib_code_signing.sh
> index 66a2cab81395..24730d3cf742 100644
> --- a/scripts/lib/ptxd_lib_code_signing.sh
> +++ b/scripts/lib/ptxd_lib_code_signing.sh
> @@ -1,6 +1,7 @@
>  #!/bin/bash
>  #
>  # Copyright (C) 2019 Sascha Hauer <s.hauer@pengutronix.de>
> +# Copyright (C) 2021 Roland Hieber, Pengutronix <rhi@pengutronix.de>
>  #
>  # For further information about the PTXdist project and license conditions
>  # see the README file.
> @@ -176,6 +177,12 @@ export -f cs_set_uri
>  # Get the uri from a role
>  #
>  cs_get_uri() {
> +    if [ -z "${pkg_name}" ]; then
> +	    echo ERROR_UNSUPPORTED_CS_API_CALL
> +	    ptxd_bailout '$(shell cs_get_uri, <role>) is no longer supported in make files.' \
> +		'Use $(call ptx/cs-get-uri, <PKG>, <role>) instead.'
> +    fi
> +
>      local role="${1}"
>      cs_init_variables
>  
> @@ -297,6 +304,12 @@ export -f cs_import_key_from_pem
>  # Get the path to the CA in pem format from a role
>  #
>  cs_get_ca() {
> +    if [ -z "${pkg_name}" ]; then
> +	    echo ERROR_UNSUPPORTED_CS_API_CALL
> +	    ptxd_bailout '$(shell cs_get_ca, …) is no longer supported in make files.' \
> +		'Use $(call ptx/cs-get-ca, <PKG>, …) instead.'
> +    fi
> +
>      local role="${1}"
>      cs_init_variables
>  
> -- 
> 2.30.2
> 
> 
> _______________________________________________
> ptxdist mailing list
> ptxdist@pengutronix.de
> To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
ptxdist mailing list
ptxdist@pengutronix.de
To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ptxdist] [PATCH v1 5/5] ptxd_lib_code_signing: add key whitelist checks
  2021-08-04 14:23 ` [ptxdist] [PATCH v1 5/5] ptxd_lib_code_signing: add key whitelist checks Roland Hieber
@ 2021-08-04 15:58   ` Michael Olbrich
  0 siblings, 0 replies; 7+ messages in thread
From: Michael Olbrich @ 2021-08-04 15:58 UTC (permalink / raw)
  To: Roland Hieber, ptxdist

On Wed, Aug 04, 2021 at 04:23:30PM +0200, Roland Hieber wrote:
> Signed-off-by: Roland Hieber <rhi@pengutronix.de>
> ---
>  doc/dev_code_signing.rst                  | 68 +++++++++++++++++++++++
>  platforms/code-signing.in                 | 22 ++++++++
>  rules/pre/030-code-signing-consumers.make |  6 ++
>  scripts/lib/ptxd_lib_code_signing.sh      | 52 ++++++++++++++++-
>  4 files changed, 147 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/dev_code_signing.rst b/doc/dev_code_signing.rst
> index 413f694980eb..aaaaae0d9107 100644
> --- a/doc/dev_code_signing.rst
> +++ b/doc/dev_code_signing.rst
> @@ -172,3 +172,71 @@ also via an environment variable.
>    (``=``, not ``:=``).
>    Otherwise the variable is expanded before a code signing provider can perform
>    its setup.
> +
> +Key Whitelisting
> +~~~~~~~~~~~~~~~~
> +
> +In some use cases, it may be feasible to do additional checks to make sure that
> +a package uses the correct key material.
> +For example, suppose you have a "development" code signing provider (e.g. with a
> +SoftHSM workflow) which you use to sign your development kernels,
> +and a "release" provider (e.g. on a HSM) which you use to sign your release kernels,
> +and a "development" and "release" variant of the bootloader which only boots
> +kernels that have been signed with the respective development or release key.
> +Now you might want to prevent the "release" bootloader from accidentally being
> +provided with the key for the "development" kernel –
> +otherwise someone could boot a development kernel on an actual production
> +board, and use the additional debugging features of the kernel to do things
> +with it that it was not meant to do.

I don't think this is a good example and somewhat confusing. It's just fine
to add development (public) keys to a bootloader with a 'release'
configuration, as long as the bootloader is also signed with a development
key.
And validation if release and development keys are mixed is not possible
with this mechanism. But that should not be a problem, because release and
development keys should not be available at the same time. Maybe the public
keys of the release keys could be added when otherwise using development
keys, but that must be handled in the provider.

A better example would be a bootloader with a development configuration
that should not be signed with a release key. But the reverse is just fine.

And please don't just use "release bootloader", that's ambiguous. There is
the feature set or configuration, and there is the key. And we can gave
'development' and 'release' for both.
And 3 of the 4 possible combinations are ok and one is not.

> +
> +When the ``CODE_SIGNING_REQUIRE_WHITELIST`` kconfig symbol is enabled,
> +the consumer functions :ref:`ptx/cs-get-ca` and :ref:`ptx/cs-get-uri`
> +look up the triplet of package name, role name, and the pubkey's SHA256
> +fingerprint in a whitelist, whose file name is determined by the
> +``CODE_SIGNING_WHITELIST_FILENAME`` kconfig symbol (the default path is
> +``configs/platform-<name>/code-signing-whitelist``).
> +If a key or a CA is not whitelisted for the package in which it is to be used,
> +the functions will exit with an error message on the terminal::
> +
> +   $ ptxdist -v print KERNEL_MAKE_OPT
> +   ptxdist: error: SPKI whitelist record 'kernel kernel-modules
> +   69C9BBB8BB4DFAE74AB21D06DFB5F2C67066373AE545453276847340822CDF04' not found in
> +   distrokit/configs/platform-v7a/code-signing-whitelist
> +
> +   …/ptxdist/rules/kernel.make:196: *** cs-get-uri: whitelist check failed, see errors above.  Stop.
> +
> +
> +If ``CODE_SIGNING_REQUIRE_WHITELIST`` is disabled (the default),
> +all keys and CAs are provided to all packages without further checks.
> +
> +The format of the code signing whitelist consists of one triplet per line, in
> +which the elements of the triplet are separated by whitespace.
> +If a CA is to be checked, the role name is prefixed with a literal ``ca:``.
> +All other unmatched lines in the file are ignored, but we suggest to use ``#``
> +to start a line comment so as not to add a whitelist record accidentally.
> +
> +For example, here is a whitelist for use with the *devel* code provider which
> +allows all provided keys to be used by their respective consumers::
> +
> +   # format: package-name role-name sha256-pubkey-fingerprint
> +   kernel      kernel-modules 69C9BBB8BB4DFAE74AB21D06DFB5F2C67066373AE545453276847340822CDF04
> +   image-rauc  update         0034F8FE5ADC3B0DFE642407275D144DE2398C68CC9A86DD6703D7151116B44E
> +   image-rauc  ca:update      0034F8FE5ADC3B0DFE642407275D144DE2398C68CC9A86DD6703D7151116B44E
> +   rauc        ca:update      0034F8FE5ADC3B0DFE642407275D144DE2398C68CC9A86DD6703D7151116B44E
> +
> +.. note:: The match is case-sensitive, and the fingerprints are expected
> +   in uppercase.
> +
> +   If a CA consists of more than one certificate, all of their fingerprints
> +   must be whitelisted.
> +
> +You can determine the key fingerprints by copying it from the error message,
> +or with the `spki-hash`__ tool from the ``host-extract-cert`` package,
> +or with openssl::
> +
> +   $ openssl pkey -in keyfile.pem -pubout -outform der \
> +     | openssl sha256 \
> +     | tr 'a-z' 'A-Z'
> +   (STDIN)= 69C9BBB8BB4DFAE74AB21D06DFB5F2C67066373AE545453276847340822CDF04
> +
> +__ https://git.pengutronix.de/cgit/extract-cert/tree/spki-hash.c
> diff --git a/platforms/code-signing.in b/platforms/code-signing.in
> index 81f9ef6f3c9e..92f555c7e965 100644
> --- a/platforms/code-signing.in
> +++ b/platforms/code-signing.in
> @@ -20,4 +20,26 @@ source "generated/code_signing_provider.in"
>  
>  endchoice
>  
> +config CODE_SIGNING_REQUIRE_WHITELISTED_KEYS
> +	bool
> +	prompt "require whitelisted keys"
> +	help
> +	  Every time a key from the code provider is used, check if the consumer
> +	  is allowed to use it.
> +
> +	  Code signing consumers can depend on this option if they want to force
> +	  the key whitelist check.
> +
> +if CODE_SIGNING_REQUIRE_WHITELISTED_KEYS
> +
> +config CODE_SIGNING_WHITELIST_FILENAME
> +	string
> +	prompt "whitelist file name"
> +	default "code-signing-whitelist"
> +	help
> +	  This file name is used for the key whitelist. The path is relative to
> +	  PTXDIST_PLATFORMCONFIGDIR (e.g. configs/platform-nnn/).
> +
> +endif # CODE_SIGNING_REQUIRE_WHITELISTED_KEYS
> +
>  endif
> diff --git a/rules/pre/030-code-signing-consumers.make b/rules/pre/030-code-signing-consumers.make
> index 72ee8e63b7b9..439db626dd14 100644
> --- a/rules/pre/030-code-signing-consumers.make
> +++ b/rules/pre/030-code-signing-consumers.make
> @@ -27,6 +27,9 @@ ptx/cs-get-uri = \
>  			$(call ptx/cs-consumer-env, $(1))\
>  				cs_get_uri '$(strip $(2))'\
>  		)\
> +		$(if $(filter-out 0,$(.SHELLSTATUS)),\
> +			$(error cs-get-uri: whitelist check failed, see errors above)\

Use ptx/error. There are cases where the output of $(error ...) gets lost.

> +		)\
>  	)
>  
>  #
> @@ -38,4 +41,7 @@ ptx/cs-get-ca = \
>  			$(call ptx/cs-consumer-env, $(1))\
>  				cs_get_ca '$(strip $(2))'\
>  		)\
> +		$(if $(filter-out 0,$(.SHELLSTATUS)),\
> +			$(error cs-get-ca: whitelist check failed, see errors above)\
> +		)\
>  	)
> diff --git a/scripts/lib/ptxd_lib_code_signing.sh b/scripts/lib/ptxd_lib_code_signing.sh
> index 24730d3cf742..332bab22e7c8 100644
> --- a/scripts/lib/ptxd_lib_code_signing.sh
> +++ b/scripts/lib/ptxd_lib_code_signing.sh
> @@ -1,6 +1,7 @@
>  #!/bin/bash
>  #
>  # Copyright (C) 2019 Sascha Hauer <s.hauer@pengutronix.de>
> +# Copyright (C) 2020 Jan Luebbe <j.luebbe@pengutronix.de>
>  # Copyright (C) 2021 Roland Hieber, Pengutronix <rhi@pengutronix.de>
>  #
>  # For further information about the PTXdist project and license conditions
> @@ -70,6 +71,7 @@ cs_init_variables() {
>      sysroot="$(ptxd_get_ptxconf PTXCONF_SYSROOT_HOST)"
>      keyprovider="$(ptxd_get_ptxconf PTXCONF_CODE_SIGNING_PROVIDER)"
>      keydir="${sysroot}/var/lib/keys/${keyprovider}"
> +    whitelist="$(ptxd_get_ptxconf PTXCONF_CODE_SIGNING_WHITELIST_FILENAME || true)"
>  }
>  export -f cs_init_variables
>  
> @@ -157,6 +159,40 @@ cs_group_get_roles() {
>  }
>  export -f cs_group_get_roles
>  
> +#
> +# cs_check_whitelisted <role> <uri/pem or fingerprint prefixed with "sha256:">
> +#
> +# Checks if the SPKI (Subject Public Key Info) Hash is in the whitelist
> +#
> +cs_check_whitelisted() {
> +    local role="${1:-ERROR_ROLE_IS_EMPTY}"
> +    local src="${2}"
> +
> +    if [ "$(ptxd_get_ptxconf PTXCONF_CODE_SIGNING_REQUIRE_WHITELISTED_KEYS)" != "y" ]; then
> +	return
> +    fi
> +
> +    if ! ptxd_in_path PTXDIST_PATH_PLATFORMCONFIGDIR "${whitelist}"; then

	echo ERROR_KEY_NOT_WHITELISTED

> +	ptxd_bailout "${pkg_name}: SPKI hash whitelist check for ${role} (${src}) is required, but configs/<platform>/${whitelist} is missing."
> +    fi
> +    local whitelist_path="${ptxd_reply}"
> +
> +    local hash
> +    if [ "${src#sha256:}" != "${src}" ]; then
> +	hash="${src#sha256:}"
> +    else
> +	hash=$(ptxd_exec_silent_stderr spki-hash "${src}")
> +    fi
> +    hash=${hash:-ERROR_HASH_IS_EMPTY}
> +    needle="${pkg_name}\s\+${role}\s\+${hash}"

needle should be local.

> +
> +    if ! grep -q --line-regexp "${needle}" "${whitelist_path}"; then
> +	echo ERROR_KEY_NOT_WHITELISTED
> +	ptxd_bailout "SPKI whitelist record '${pkg_name} ${role} ${hash}' not found in $(ptxd_print_path "${whitelist_path}")"
> +    fi
> +}
> +export -f cs_check_whitelisted
> +
>  #
>  # cs_set_uri <role> <uri>
>  #
> @@ -198,7 +234,12 @@ cs_get_uri() {
>  	    return
>  	fi
>      fi
> -    cat "${keydir}/${role}/uri"
> +
> +    local uri=$(cat "${keydir}/${role}/uri")
> +    if [ -z "${cs_no_whitelist_check}" ]; then
> +	cs_check_whitelisted "${role}" "${uri}"
> +    fi
> +    echo "${uri}"
>  }
>  export -f cs_get_uri
>  
> @@ -321,6 +362,9 @@ cs_get_ca() {
>      fi
>  
>      if [ -e "${ca}" ]; then
> +	while read fp; do
> +	    cs_check_whitelisted "ca:${role}" "sha256:${fp}"
> +	done < "${keydir}/${role}/ca.fingerprints"
>  	echo "${ca}"
>      fi
>  }
> @@ -339,6 +383,9 @@ cs_append_ca_from_pem() {
>      cat "${pem}" >> "${keydir}/${role}/ca.pem"
>      # add new line in case ${pem} does not end with an EOL
>      echo >> "${keydir}/${role}/ca.pem"
> +
> +    openssl x509 -in "${pem}" -inform pem -noout -pubkey | \
> +	spki-hash /dev/stdin >> "${keydir}/${role}/ca.fingerprints"
>  }
>  export -f cs_append_ca_from_pem
>  
> @@ -370,7 +417,10 @@ cs_append_ca_from_uri() {
>      cs_init_variables
>  
>      if [ -z "${uri}" ]; then
> +	# cs_append_ca_from_der will check this later
> +	local cs_no_whitelist_check=1
>  	uri=$(cs_get_uri "${role}")
> +	unset cs_no_whitelist_check

I prefer a cs_get_uri_unchecked() function (or something like that) and
call that on here and in cs_get_uri().

Michael

>      fi
>  
>      ptxd_exec extract-cert "${uri}" "${tmpdir}/ca.der" &&
> -- 
> 2.30.2
> 
> 
> _______________________________________________
> ptxdist mailing list
> ptxdist@pengutronix.de
> To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
ptxdist mailing list
ptxdist@pengutronix.de
To unsubscribe, send a mail with subject "unsubscribe" to ptxdist-request@pengutronix.de

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-08-04 15:58 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-04 14:23 [ptxdist] [PATCH v1 1/5] ptxd_make_world_common: make the package name available to scripts Roland Hieber
2021-08-04 14:23 ` [ptxdist] [PATCH v1 2/5] libptxdist: introduce ptxd_exec_silent_stderr Roland Hieber
2021-08-04 14:23 ` [ptxdist] [PATCH v1 3/5] ptxd_lib_code_signing: refactor hard-coded SoftHSM PIN in PKCS11 URIs Roland Hieber
2021-08-04 14:23 ` [ptxdist] [PATCH v1 4/5] ptxd_lib_code_signing: provide consumer functions with some environment Roland Hieber
2021-08-04 15:23   ` Michael Olbrich
2021-08-04 14:23 ` [ptxdist] [PATCH v1 5/5] ptxd_lib_code_signing: add key whitelist checks Roland Hieber
2021-08-04 15:58   ` Michael Olbrich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox