[meta-swupdate][PATCH 1/2] Write image sha256 hashs to sw-description

196 views
Skip to first unread message

George McCollister

unread,
Apr 28, 2016, 12:31:13 PM4/28/16
to swup...@googlegroups.com, George McCollister
Replace occurrences of @IMAGE (where IMAGE is the filename of an image)
in sw-description with the sha256 hash of the image during creation of
the swu file.

Example sw-description snippet:
{
filename = "core-image-full-cmdline-beaglebone.ext3";
device = "/dev/mmcblk1p2";
type = "raw";
sha256 = "@core-image-full-cmdline-beaglebone.ext3";
}

Signed-off-by: George McCollister <george.mc...@gmail.com>
---
README | 6 ++++++
classes/swupdate.bbclass | 44 ++++++++++++++++++++++++++++++++++++++++----
2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/README b/README
index b987885..2df2bf6 100644
--- a/README
+++ b/README
@@ -12,6 +12,12 @@ This layer depends on:
URI: git://github.com/openembedded/meta-openembedded.git
subdirectory: meta-oe

+Image hashing
+-------------
+
+During creation of the update file, occurrences of @IMAGE (where IMAGE is an
+image filename) are replaced with the sha256 hash of the image.
+
Maintainer
----------

diff --git a/classes/swupdate.bbclass b/classes/swupdate.bbclass
index 4c29337..c8d8112 100644
--- a/classes/swupdate.bbclass
+++ b/classes/swupdate.bbclass
@@ -16,6 +16,37 @@ S = "${WORKDIR}/${PN}"

IMAGE_DEPENDS ?= ""

+def swupdate_is_hash_needed(s, filename):
+ with open(os.path.join(s, "sw-description"), 'r') as f:
+ for line in f:
+ if line.find("@%s" % (filename)) != -1:
+ return True
+ return False
+
+def swupdate_get_sha256(s, filename):
+ import hashlib
+
+ m = hashlib.sha256()
+
+ with open(os.path.join(s, filename), 'rb') as f:
+ while True:
+ data = f.read(1024)
+ if not data:
+ break
+ m.update(data)
+ return m.hexdigest()
+
+def swupdate_write_sha256(s, filename, hash):
+ write_lines = []
+
+ with open(os.path.join(s, "sw-description"), 'r') as f:
+ for line in f:
+ write_lines.append(line.replace("@%s" % (filename), hash))
+
+ with open(os.path.join(s, "sw-description"), 'w+') as f:
+ for line in write_lines:
+ f.write(line)
+
def swupdate_getdepends(d):
def adddep(depstr, deps):
for i in (depstr or "").split():
@@ -67,14 +98,14 @@ python do_swuimage () {
s = d.getVar('S', True)
shutil.copyfile(os.path.join(workdir, "sw-description"), os.path.join(s, "sw-description"))
fetch = bb.fetch2.Fetch([], d)
- list_for_cpio = "sw-description"
+ list_for_cpio = ["sw-description"]

for url in fetch.urls:
local = fetch.localpath(url)
filename = os.path.basename(local)
shutil.copyfile(local, os.path.join(s, "%s" % filename ))
if (filename != 'sw-description'):
- list_for_cpio += " " + filename
+ list_for_cpio.append(filename)

deploydir = d.getVar('DEPLOY_DIR_IMAGE', True)

@@ -87,9 +118,14 @@ python do_swuimage () {
src = os.path.join(deploydir, "%s" % imagename)
dst = os.path.join(s, "%s" % imagename)
shutil.copyfile(src, dst)
- list_for_cpio += " " + imagename
+ list_for_cpio.append(imagename)
+
+ for file in list_for_cpio:
+ if file != 'sw-description' and swupdate_is_hash_needed(s, file):
+ hash = swupdate_get_sha256(s, file)
+ swupdate_write_sha256(s, file, hash)

- line = 'for i in ' + list_for_cpio + '; do echo $i;done | cpio -ov -H crc >' + os.path.join(deploydir,d.getVar('IMAGE_NAME', True) + '.swu')
+ line = 'for i in ' + ' '.join(list_for_cpio) + '; do echo $i;done | cpio -ov -H crc >' + os.path.join(deploydir,d.getVar('IMAGE_NAME', True) + '.swu')
os.system("cd " + s + ";" + line)
}

--
2.8.0

George McCollister

unread,
Apr 28, 2016, 12:31:16 PM4/28/16
to swup...@googlegroups.com, George McCollister
If SWUPDATE_SIGNING is set to "1" use openssl to sign sw-description
with SWUPDATE_PRIVATE_KEY and write the signature to sw-description.sig.
Include sw-description.sig in the SWU archive.

Encrypted private keys are not currently supported since a secure
mechanism must exist to provide the passphrase. The best solution may be
to use a smartcard compatible hardware module rather than storing the
key on the filesystem. Expect patches to add support for this in the
future.

Signed-off-by: George McCollister <george.mc...@gmail.com>
---
README | 13 +++++++++++++
classes/swupdate.bbclass | 17 +++++++++++++++++
2 files changed, 30 insertions(+)

diff --git a/README b/README
index 2df2bf6..85faf8f 100644
--- a/README
+++ b/README
@@ -18,6 +18,19 @@ Image hashing
During creation of the update file, occurrences of @IMAGE (where IMAGE is an
image filename) are replaced with the sha256 hash of the image.

+SWU image signing
+------------
+
+To enable signing:
+ Set SWUPDATE_SIGNING = "1"
+ Set SWUPDATE_PRIVATE_KEY to the full path of private key file
+
+sw-description is signed with the private key and the signature is writen to
+sw-description.sig which is included in the SWU file.
+
+Encrypted private keys are not currently supported since a secure
+mechanism must exist to provide the passphrase.
+
Maintainer
----------

diff --git a/classes/swupdate.bbclass b/classes/swupdate.bbclass
index c8d8112..84e709f 100644
--- a/classes/swupdate.bbclass
+++ b/classes/swupdate.bbclass
@@ -14,6 +14,7 @@

S = "${WORKDIR}/${PN}"

+DEPENDS += "${@ 'openssl-native' if d.getVar('SWUPDATE_SIGNING', True) == '1' else ''}"
IMAGE_DEPENDS ?= ""

def swupdate_is_hash_needed(s, filename):
@@ -109,6 +110,9 @@ python do_swuimage () {

deploydir = d.getVar('DEPLOY_DIR_IMAGE', True)

+ if d.getVar('SWUPDATE_SIGNING', True) == '1':
+ list_for_cpio.append('sw-description.sig')
+
for image in images:
imagename = image + '-' + d.getVar('MACHINE', True)
fstypes = (d.getVarFlag("SWUPDATE_IMAGES_FSTYPES", image, True) or "").split()
@@ -125,6 +129,19 @@ python do_swuimage () {
hash = swupdate_get_sha256(s, file)
swupdate_write_sha256(s, file, hash)

+ if d.getVar('SWUPDATE_SIGNING', True) == '1':
+ privkey = d.getVar('SWUPDATE_PRIVATE_KEY', True)
+ if not privkey:
+ bb.fatal("SWUPDATE_PRIVATE_KEY isn't set")
+ if not os.path.exists(privkey):
+ bb.fatal("SWUPDATE_PRIVATE_KEY %s doesn't exist" % (privkey))
+ signcmd = "openssl dgst -sha256 -sign '%s' -out '%s' '%s'" % (
+ privkey,
+ os.path.join(s, 'sw-description.sig'),
+ os.path.join(s, 'sw-description'))
+ if os.system(signcmd) != 0:
+ bb.fatal("Failed to sign sw-description with %s" % (privkey))

Stefano Babic

unread,
May 10, 2016, 12:45:40 PM5/10/16
to George McCollister, swup...@googlegroups.com
Appied to master, thanks !

Best regards,
Stefano Babic

--
=====================================================================
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sba...@denx.de
=====================================================================

Stefano Babic

unread,
May 10, 2016, 12:45:52 PM5/10/16
to George McCollister, swup...@googlegroups.com
On 28/04/2016 18:30, George McCollister wrote:
Reply all
Reply to author
Forward
0 new messages