diff mbox series

[meta-swupdate,1/2] swupdate-common: improve signing

Message ID 20211104181848.4185983-2-adrian.freihofer@siemens.com
State Changes Requested
Headers show
Series fix build-time signing issues | expand

Commit Message

Adrian Freihofer Nov. 4, 2021, 6:18 p.m. UTC
Improve the implementation of signatures and related task dependencies.

os.system gets replaced by subprocess.run. os.system does not display helpful
error messages and therefore signing fails without a useful error description.
Since os.system has been replaced by the more modern subprocess.run, some
interesting error patterns have become visible. In particular, when running
more complex build flows when rm_work was active, the signing step sometimes
failed becaus:

- openssl binary not found: fixed dependencies
- openssl fails because the parameter "-passin file:'%s' " is invalid.
  With the list-based syntax of subprocess.run, this is handled without '

Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
 classes/swupdate-common.bbclass | 70 ++++++++++++++-------------------
 1 file changed, 30 insertions(+), 40 deletions(-)
diff mbox series

Patch

diff --git a/classes/swupdate-common.bbclass b/classes/swupdate-common.bbclass
index f483398..9d81cfb 100644
--- a/classes/swupdate-common.bbclass
+++ b/classes/swupdate-common.bbclass
@@ -1,8 +1,3 @@ 
-DEPENDS += "\
-    cpio-native \
-    ${@ 'openssl-native' if d.getVar('SWUPDATE_SIGNING', True) else ''} \
-"
-
 do_swuimage[umask] = "022"
 SSTATETASKS += "do_swuimage"
 SSTATE_SKIP_CREATION_task-swuimage = '1'
@@ -15,26 +10,36 @@  do_swuimage[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}"
 do_swuimage[stamp-extra-info] = "${MACHINE}"
 
 python () {
-    deps = " " + swupdate_getdepends(d)
+    deps = " " + swuimage_getdepends(d)
     d.appendVarFlag('do_swuimage', 'depends', deps)
     d.delVarFlag('do_fetch', 'noexec')
     d.delVarFlag('do_unpack', 'noexec')
 }
 
-def swupdate_getdepends(d):
+def swuimage_getdepends(d):
     def adddep(depstr, deps):
         for i in (depstr or "").split():
             if i not in deps:
                 deps.append(i)
 
+    # Artifacts
     deps = []
     images = (d.getVar('IMAGE_DEPENDS', True) or "").split()
     for image in images:
-            adddep(image , deps)
+        adddep(image , deps)
 
     depstr = ""
     for dep in deps:
         depstr += " " + dep + ":do_build"
+
+    # openssl
+    if d.getVar('SWUPDATE_SIGNING') or d.getVar('SWUPDATE_ENCRYPT_SWDESC') or d.getVarFlags('SWUPDATE_IMAGES_ENCRYPTED'):
+        depstr += " openssl-native:do_populate_sysroot"
+    # cpio
+    depstr += " cpio-native:do_populate_sysroot"
+    # Always (also with rm_work active) files to workdir
+    depstr += ' ' + d.getVar('PN') + ":do_unpack"
+
     return depstr
 
 def swupdate_get_sha256(s, filename):
@@ -228,6 +233,7 @@  def swupdate_expand_auto_versions(d, s):
 
 def prepare_sw_description(d):
     import shutil
+    import subprocess
 
     s = d.getVar('S', True)
     swupdate_expand_bitbake_variables(d, s)
@@ -247,13 +253,19 @@  def prepare_sw_description(d):
         bb.warn('SWUPDATE_SIGNING = "1" is deprecated, falling back to "RSA". It is advised to set it to "RSA" if using RSA signing.')
         signing = "RSA"
     if signing:
+        def get_pwd_file_args():
+            pwd_args = []
+            pwd_file = d.getVar('SWUPDATE_PASSWORD_FILE', True)
+            if pwd_file:
+                pwd_args = ["-passin", "file:%s" % pwd_file]
+            return pwd_args
+
+        sw_desc_sig = os.path.join(s, 'sw-description.sig')
+        sw_desc =  os.path.join(s, 'sw-description.plain' if encrypt else 'sw-description')
+
         if signing == "CUSTOM":
-            sign_tool = d.getVar('SWUPDATE_SIGN_TOOL', True)
-            if sign_tool:
-                ret = os.system(sign_tool)
-                if ret != 0:
-                    bb.fatal("Failed to sign with %s" % (sign_tool))
-            else:
+            signcmd = d.getVar('SWUPDATE_SIGN_TOOL', True)
+            if not sign_tool:
                 bb.fatal("Custom SWUPDATE_SIGN_TOOL is not given")
         elif signing == "RSA":
             privkey = d.getVar('SWUPDATE_PRIVATE_KEY', True)
@@ -261,18 +273,7 @@  def prepare_sw_description(d):
                 bb.fatal("SWUPDATE_PRIVATE_KEY isn't set")
             if not os.path.exists(privkey):
                 bb.fatal("SWUPDATE_PRIVATE_KEY %s doesn't exist" % (privkey))
-            passout = d.getVar('SWUPDATE_PASSWORD_FILE', True)
-            if passout:
-                passout = "-passin file:'%s' " % (passout)
-            else:
-                passout = ""
-            signcmd = "openssl dgst -sha256 -sign '%s' %s -out '%s' '%s'" % (
-                privkey,
-                passout,
-                os.path.join(s, 'sw-description.sig'),
-                os.path.join(s, 'sw-description.plain' if encrypt else 'sw-description'))
-            if os.system(signcmd) != 0:
-                bb.fatal("Failed to sign sw-description with %s" % (privkey))
+            signcmd = ["openssl", "dgst", "-sha256", "-sign", privkey] + get_pwd_file_args() + ["-out", sw_desc_sig, sw_desc]
         elif signing == "CMS":
             cms_cert = d.getVar('SWUPDATE_CMS_CERT', True)
             if not cms_cert:
@@ -284,21 +285,10 @@  def prepare_sw_description(d):
                 bb.fatal("SWUPDATE_CMS_KEY isn't set")
             if not os.path.exists(cms_key):
                 bb.fatal("SWUPDATE_CMS_KEY %s doesn't exist" % (cms_key))
-            passout = d.getVar('SWUPDATE_PASSWORD_FILE', True)
-            if passout:
-                passout = "-passin file:'%s' " % (passout)
-            else:
-                passout = ""
-            signcmd = "openssl cms -sign -in '%s' -out '%s' -signer '%s' -inkey '%s' %s -outform DER -nosmimecap -binary" % (
-                os.path.join(s, 'sw-description.plain' if encrypt else 'sw-description'),
-                os.path.join(s, 'sw-description.sig'),
-                cms_cert,
-                cms_key,
-                passout)
-            if os.system(signcmd) != 0:
-                bb.fatal("Failed to sign sw-description with %s" % (privkey))
+            signcmd = ["openssl", "cms", "-sign", "-in", sw_desc, "-out", sw_desc_sig, "-signer", cms_cert, "-inkey", cms_key] + get_pwd_file_args() + ["-outform", "DER", "-nosmimecap", "-binary"]
         else:
-            bb.fatal("Unrecognized SWUPDATE_SIGNING mechanism.");
+            bb.fatal("Unrecognized SWUPDATE_SIGNING mechanism.")
+        subprocess.run(signcmd, check=True)
 
 
 def swupdate_add_src_uri(d, list_for_cpio):