diff mbox series

[meta-swupdate] swupdate: encrypt artefact when building SWU

Message ID 20201126135145.72571-1-sbabic@denx.de
State Accepted
Headers show
Series [meta-swupdate] swupdate: encrypt artefact when building SWU | expand

Commit Message

Stefano Babic Nov. 26, 2020, 1:51 p.m. UTC
Add support to swupdate.bbclass to encrypt artefacts before packing them
into the SWU. This guarantees that all artefacts are encrypted with the
same key.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 classes/swupdate-common.bbclass | 38 +++++++++++++++++++++++++++++++++
 classes/swupdate.bbclass        | 21 ++++++++++++++----
 2 files changed, 55 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/classes/swupdate-common.bbclass b/classes/swupdate-common.bbclass
index c0b302a..17c7916 100644
--- a/classes/swupdate-common.bbclass
+++ b/classes/swupdate-common.bbclass
@@ -18,6 +18,36 @@  def swupdate_get_sha256(s, filename):
             m.update(data)
     return m.hexdigest()
 
+def swupdate_extract_keys(keyfile):
+    try:
+        keys = open(keyfile)
+    except IOError:
+        bb.fatal("Failed to open file with keys %s" % (keyfile))
+    lines = keys.read()
+    keys.close()
+    lines = lines.splitlines(True)
+    for line in lines:
+        line = line.replace('\n', '')
+        kv = line.split('=')
+        if kv[0] == 'salt':
+            salt = kv[1]
+        if kv[0] == 'key':
+            key = kv[1]
+        if kv[0] == 'iv' or kv[0] == 'iv ':
+            iv = kv[1]
+    return key,iv,salt
+
+def swupdate_encrypt_file(f, out, key, ivt, salt):
+    cmd = "openssl enc -aes-256-cbc -in '%s' -out '%s' -K '%s' -iv '%s' -S '%s'" % (
+                f,
+                out,
+                key,
+                ivt,
+                salt)
+    if os.system(cmd) != 0:
+        bb.fatal("Failed to encrypt %s" % (f))
+
+
 def swupdate_write_sha256(s, filename, hash):
     write_lines = []
 
@@ -66,6 +96,7 @@  def swupdate_expand_bitbake_variables(d, s):
             f.write(line)
 
 def prepare_sw_description(d, s, list_for_cpio):
+    import shutil
 
     swupdate_expand_bitbake_variables(d, s)
 
@@ -74,6 +105,13 @@  def prepare_sw_description(d, s, list_for_cpio):
             hash = swupdate_get_sha256(s, file)
             swupdate_write_sha256(s, file, hash)
 
+    encrypt = d.getVar('SWUPDATE_ENCRYPT_SWDESC', True)
+    if encrypt:
+        bb.note("Encryption of sw-description")
+        shutil.copyfile(os.path.join(s, 'sw-description'), os.path.join(s, 'sw-description.plain'))
+        key,iv,salt = swupdate_extract_keys(d.getVar('SWUPDATE_AES_FILE', True))
+        swupdate_encrypt_file(os.path.join(s, 'sw-description.plain'), os.path.join(s, 'sw-description'), key, iv, salt)
+
     signing = d.getVar('SWUPDATE_SIGNING', True)
     if signing == "1":
         bb.warn('SWUPDATE_SIGNING = "1" is deprecated, falling back to "RSA". It is advised to set it to "RSA" if using RSA signing.')
diff --git a/classes/swupdate.bbclass b/classes/swupdate.bbclass
index c0cb7f9..b94955c 100644
--- a/classes/swupdate.bbclass
+++ b/classes/swupdate.bbclass
@@ -100,16 +100,28 @@  python do_swuimage () {
         local = fetch.localpath(url)
         filename = os.path.basename(local)
         if (filename != 'sw-description') and (os.path.isfile(local)):
-            shutil.copyfile(local, os.path.join(s, "%s" % filename ))
+            encrypted = (d.getVarFlag("SWUPDATE_IMAGES_ENCRYPTED", filename, True) or "")
+            key,iv,salt = swupdate_extract_keys(d.getVar('SWUPDATE_AES_FILE', True))
+            dst = os.path.join(s, "%s" % filename )
+            if encrypted == '1':
+                bb.note("Encryption requested for %s" %(filename))
+                swupdate_encrypt_file(local, dst, key, iv, salt)
+            else:
+                shutil.copyfile(local, dst)
             list_for_cpio.append(filename)
 
-    def add_image_to_swu(deploydir, imagename, s):
+    def add_image_to_swu(deploydir, imagename, s, encrypt):
         src = os.path.join(deploydir, imagename)
         if not os.path.isfile(src):
             return False
         target_imagename = os.path.basename(imagename)  # allow images in subfolders of DEPLOY_DIR_IMAGE
         dst = os.path.join(s, target_imagename)
-        shutil.copyfile(src, dst)
+        if encrypt == '1':
+            key,iv,salt = swupdate_extract_keys(d.getVar('SWUPDATE_AES_FILE', True))
+            bb.note("Encryption requested for %s" %(imagename))
+            swupdate_encrypt_file(src, dst, key, iv, salt)
+        else:
+            shutil.copyfile(src, dst)
         list_for_cpio.append(target_imagename)
         return True
 
@@ -118,6 +130,7 @@  python do_swuimage () {
     imgdeploydir = d.getVar('IMGDEPLOYDIR', True)
     for image in images:
         fstypes = (d.getVarFlag("SWUPDATE_IMAGES_FSTYPES", image, True) or "").split()
+        encrypted = (d.getVarFlag("SWUPDATE_IMAGES_ENCRYPTED", image, True) or "")
         if fstypes:
             noappend_machine = d.getVarFlag("SWUPDATE_IMAGES_NOAPPEND_MACHINE", image, True)
             if noappend_machine == False:  # Search for a file explicitely with MACHINE
@@ -129,7 +142,7 @@  python do_swuimage () {
             for fstype in fstypes:
                 image_found = False
                 for imagebase in imagebases:
-                    image_found = add_image_to_swu(deploydir, imagebase + fstype, s)
+                    image_found = add_image_to_swu(deploydir, imagebase + fstype, s, encrypted)
                     if image_found:
                         break
                 if not image_found: