diff mbox series

[meta-oe,v2,2/6] signing.bbclass: add set|get|has_ca functions

Message ID 20250531113252.3889951-3-johannes.schneider@leica-geosystems.com
State Accepted
Headers show
Series signing.bbclass: add certificate chain handling | expand

Commit Message

Johannes Schneider May 31, 2025, 11:32 a.m. UTC
Add a mechanism to establish a (metadata) link between roles, in the
form of a new 'ca' variable.  Which is intended to point from one role
to another, to preserve the leaf->intermediary certificate relation.

With this additional mechanism, it would be now possible to import a
complex PKI tree of certificates (either just the certificates, or
both cert+key where available); and then later during usage of one
role, reconstruct the verification chain from the leaf, through
multiple intermediary, and up to the root role.

Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
---
 meta-oe/classes/signing.bbclass | 36 ++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

Comments

Jan Lübbe June 2, 2025, 10:10 a.m. UTC | #1
On Sat, 2025-05-31 at 13:32 +0200, Johannes Schneider via lists.openembedded.org
wrote:
> Add a mechanism to establish a (metadata) link between roles, in the
> form of a new 'ca' variable.  Which is intended to point from one role
> to another, to preserve the leaf->intermediary certificate relation.

Perhaps instead:

 Add a mechanism to establish a (metadata) link between roles and signer
 certificates, in the form of a new 'ca' variable.  It must point from one 
 role or cert to the signer certificate to preserve the leaf->intermediary->
 root certificate relation.

> With this additional mechanism, it would be now possible to import a
> complex PKI tree of certificates (either just the certificates, or
> both cert+key where available); and then later during usage of one
> role, reconstruct the verification chain from the leaf, through
> multiple intermediary, and up to the root role.

Keys should be only imported for roles, not ca certificates. So perhaps:

 With this additional mechanism, it would be now possible to import a
 complex PKI tree of certificates and then later during usage of one
 role, reconstruct the certificate chain from the leaf, through
 multiple intermediary, and up to the root certificate.

Also add a note that the PKI hierarchy cannot be overridden from local.conf yet.

> Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com>
> ---
>  meta-oe/classes/signing.bbclass | 36 ++++++++++++++++++++++++++++++++-
>  1 file changed, 35 insertions(+), 1 deletion(-)
> 
> diff --git a/meta-oe/classes/signing.bbclass b/meta-oe/classes/signing.bbclass
> index c768371151..5992a75be7 100644
> --- a/meta-oe/classes/signing.bbclass
> +++ b/meta-oe/classes/signing.bbclass
> @@ -145,9 +145,43 @@ signing_import_cert_from_der() {
>      signing_pkcs11_tool --type cert --write-object "${der}" --label "${cert_name}"
>  }
>  
> -# signing_import_cert_chain_from_pem <role> <pem>
> +# signing_import_set_ca <cert_name> <ca_cert_name>
> +#
> +# Link the certificate from <cert_name> to its issuer stored in
> +# <ca_cert_name> By walking this linked list a CA-chain can later be
> +# reconstructed from the involed roles.
> +signing_import_set_ca() {
> +    local cert_name="${1}"
> +    local ca_cert_name="${2}"
> +
> +    echo "_SIGNING_CA_${cert_name}_=\"${ca_cert_name}\"" >> $_SIGNING_ENV_FILE_
> +    echo "added link from ${cert_name} to ${ca_cert_name}"
> +}
> +
> +# signing_get_ca <cert_name>
>  #
> +# returns the <ca_cert_name> that has been set previously through
> +# signing_import_set_ca; or the empty string if none was set

For cases, where the real PKI hierarchy loaded in to the real HSM differs from
the one loaded into SoftHSM, we'll need a way to override these variables. So,
similar to how signing_get_module() first checks the overrides set up from
bitbake variables by signing_class_prepare().

Then, a user could set use something the following for the provider:
  signing_import_prepare

  signing_import_cert_from_pem kernel ".../kernel-ca.crt"

  signing_import_define_role kernel_modules
  signing_import_cert_from_pem kernel_modules "${S}/kmod-development.crt"
  signing_import_key_from_pem kernel_modules "${S}/kmod-development.key"
  signing_import_set_ca kernel_modules kernel

  signing_import_define_role kernel_ipe
  signing_import_cert_from_pem kernel_ipe "${S}/ipe-development.crt"
  signing_import_key_from_pem kernel_ipe "${S}/ipe-development.key"
  signing_import_set_ca kernel_ipe kernel

  signing_import_finish

For release builds, in addition to overriding URIs for the role, you'd need to
override the certificates as well in your local.conf with something like this:
 SIGNING_PKCS11_MODULE = "/usr/lib/x86_64-linux-gnu/opensc-pkcs11.so"
 SIGNING_PKCS11_URI[kernel_modules] = "pkcs11:serial=DENK0200554;object=production-kernel-modules&pin-value=123456"
 SIGNING_PKCS11_URI[kernel_modules] = "kernel_inter"
 SIGNING_PKCS11_URI[kernel_inter] = "pkcs11:serial=DENK0200554;object=production-kernel-inter&pin-value=123456"
 SIGNING_PKCS11_URI[kernel_inter] = "kernel_ca"
 SIGNING_PKCS11_URI[kernel_ca] = "pkcs11:serial=DENK0200554;object=production-kernel-ca&pin-value=123456"

In this case, the real hierarchy has an additional intermediate certificate that
is not part of the one used during development. Perhaps also support simply a
file URL or path for the certs, so that it doesn't have to be imported to the
HSM, depending how we implement it later.

This doesn't need to be implemented here, yet, as long the limitation is
documented (also in the class comment).

> +signing_get_ca() {
> +    local cert_name="${1}"
>  
> +    eval local ca_cert_name="\$_SIGNING_CA_${cert_name}_"
> +    echo "$ca_cert_name"
> +}
> +
> +# signing_has_ca <cert_name>
> +#
> +# check if the cert_name links to another cert_name that is its
> +# certificate authority/issuer.
> +signing_has_ca() {
> +    local ca_cert_name="$(signing_get_ca ${1})"
> +
> +    test -n "$ca_cert_name"
> +    return $?
> +}
> +
> +# signing_import_cert_chain_from_pem <role> <pem>
> +#
>  # Import a certificate *chain* from a PEM file to a role.
>  # (e.g. multiple ones concatenated in one file)
>  #
> 

Regards,
Jan
diff mbox series

Patch

diff --git a/meta-oe/classes/signing.bbclass b/meta-oe/classes/signing.bbclass
index c768371151..5992a75be7 100644
--- a/meta-oe/classes/signing.bbclass
+++ b/meta-oe/classes/signing.bbclass
@@ -145,9 +145,43 @@  signing_import_cert_from_der() {
     signing_pkcs11_tool --type cert --write-object "${der}" --label "${cert_name}"
 }
 
-# signing_import_cert_chain_from_pem <role> <pem>
+# signing_import_set_ca <cert_name> <ca_cert_name>
+#
+# Link the certificate from <cert_name> to its issuer stored in
+# <ca_cert_name> By walking this linked list a CA-chain can later be
+# reconstructed from the involed roles.
+signing_import_set_ca() {
+    local cert_name="${1}"
+    local ca_cert_name="${2}"
+
+    echo "_SIGNING_CA_${cert_name}_=\"${ca_cert_name}\"" >> $_SIGNING_ENV_FILE_
+    echo "added link from ${cert_name} to ${ca_cert_name}"
+}
+
+# signing_get_ca <cert_name>
 #
+# returns the <ca_cert_name> that has been set previously through
+# signing_import_set_ca; or the empty string if none was set
+signing_get_ca() {
+    local cert_name="${1}"
 
+    eval local ca_cert_name="\$_SIGNING_CA_${cert_name}_"
+    echo "$ca_cert_name"
+}
+
+# signing_has_ca <cert_name>
+#
+# check if the cert_name links to another cert_name that is its
+# certificate authority/issuer.
+signing_has_ca() {
+    local ca_cert_name="$(signing_get_ca ${1})"
+
+    test -n "$ca_cert_name"
+    return $?
+}
+
+# signing_import_cert_chain_from_pem <role> <pem>
+#
 # Import a certificate *chain* from a PEM file to a role.
 # (e.g. multiple ones concatenated in one file)
 #