[linux-signed] 02/05: Add skeleton of signing script and makefile rule

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Mon Apr 4 18:39:11 UTC 2016


This is an automated email from the git hooks/post-receive script.

benh pushed a commit to branch master
in repository linux-signed.

commit d8162b29533038e4e5b779682f653370519a76a3
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Sun Apr 3 20:38:03 2016 +0100

    Add skeleton of signing script and makefile rule
---
 debian/.gitignore    |   1 +
 debian/README.source |  46 ++++++++++++++++++++++
 debian/bin/sign.py   | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++
 debian/rules         |   8 +++-
 debian/rules.defs    |   7 ++++
 debian/rules.real    |   2 +
 6 files changed, 167 insertions(+), 2 deletions(-)

diff --git a/debian/.gitignore b/debian/.gitignore
index 08f76f2..5eeee81 100644
--- a/debian/.gitignore
+++ b/debian/.gitignore
@@ -6,6 +6,7 @@
 /control*
 /files
 /linux-image-*
+/localpackages/
 /rules.gen
 /source.lintian-overrides
 /stamps/
diff --git a/debian/README.source b/debian/README.source
new file mode 100644
index 0000000..c8a9a31
--- /dev/null
+++ b/debian/README.source
@@ -0,0 +1,46 @@
+NOTE: This package can only be updated by the holder of a signing key
+trusted by the linux-image packages.  This is currently Ben Hutchings,
+but in future will be the FTP masters.
+
+All signatures are made at source preparation time, not during a
+build.  This avoids the need to expose signing keys to buildds and
+allows reproducible builds.
+
+When preparing a source package, you will need sbsigntool and the
+appropriate versions of the linux-kbuild and linux-support packages
+installed.  All the linux-image package must have already been built
+(but not installed).
+
+To generate a key pair and *self-signed* certificate: for testing,
+run:
+
+    openssl genrsa -out foo.key.priv.pem 2048
+    openssl req -key foo.key.priv.pem -out foo.req.pem -new
+    openssl x509 -in foo.req.pem -req -signkey foo.key.priv.pem -out foo.cer.pem
+
+For module signing you need a DER fomat certificate, so add
+'-outform der' to the last comand.
+
+To generate the signatures:
+
+1. Uupdate debian/rules.defs:
+   - KERNEL_ABINAME: The kernel ABI name as included in all
+     linux-image package names, e.g. 4.5.0-trunk.
+   - KERNEL_IMAGE_VERSION: Version of the linux-image packages to be
+     signed.
+   - KERNEL_MODULES_PRIVKEY: Name of the private key file (RSA PEM
+     format) for module signing.
+   - KERNEL_MODULES_CERT: Name of the certificate file (X.509 PEM
+     format) for module signing.  This file must also be included in
+     src:linux and listed in CONFIG_SYSTEM_TRUSTED_KEYS.
+   - KERNEL_IMAGE_PRIVKEY: Name of the private key file (RSA PEM
+     format) for image signing.
+   - KERNEL_IMAGE_CERT: Name of the certificate file (X.509 PEM
+     format) for image signing.  This certificate must be trusted by
+     the boot loader for Secure Boot to work.
+2. If the packages are not yet publicly available (e.g. for a security
+   update), create debian/localpackages/ and copy or link them into
+   there.
+3. Run 'debian/rules sign'
+
+ -- Ben Hutchings <ben at decadent.org.uk>, Mon,  4 Apr 2016 16:48:16 +0100
diff --git a/debian/bin/sign.py b/debian/bin/sign.py
new file mode 100755
index 0000000..a2d3878
--- /dev/null
+++ b/debian/bin/sign.py
@@ -0,0 +1,105 @@
+#!/usr/bin/python3
+
+import sys
+sys.path.append(sys.argv[1] + "/lib/python")
+
+import os, os.path, shutil, tempfile
+
+from debian_linux.config import ConfigCoreDump
+from debian_linux.debian import VersionLinux
+
+def get_package(name, version, arch):
+    packages_dir = 'debian/localpackages/'
+    package_file = '%s/%s_%s_%s.deb' % (packages_dir, name, version, arch)
+    unpack_dir = '%s/%s_%s_%s' % (packages_dir, name, version, arch)
+
+    # FIXME Need a way to download for any architecture with signature
+    # verification
+    os.makedirs(packages_dir, exist_ok=True)
+    if not os.path.isfile(package_file):
+        if os.system('debsnap -d %s -f --binary -a %s %s %s' %
+                     (packages_dir, arch, name, version)):
+            raise Exception('debsnap failed')
+
+    if not os.path.isdir(unpack_dir):
+        # Unpack to a temporary directory before moving into place, so we
+        # don't cache a half-unpacked package
+        unpack_temp_dir = unpack_dir + '.temp'
+        if os.path.isdir(unpack_temp_dir):
+            shutil.rmtree(unpack_temp_dir)
+        os.makedirs(unpack_temp_dir)
+        if os.system('dpkg-deb -x %s %s' % (package_file, unpack_temp_dir)):
+            raise Exception('dpkg-deb failed')
+        os.rename(unpack_temp_dir, unpack_dir)
+
+    return unpack_dir
+
+def sign_module(module_name, signature_name, privkey_name, cert_name):
+    print('Should sign module %s with %s/%s and detach signature as %s' %
+          (module_name, privkey_name, cert_name, signature_name))
+
+def sign_modules(modules_dir, signature_dir, privkey_name, cert_name):
+    for walk_dir, subdir_names, file_names in os.walk(modules_dir):
+        rel_dir = os.path.relpath(walk_dir, modules_dir)
+        for rel_name in file_names:
+            if rel_name.endswith('.ko'):
+                sign_module(os.path.join(walk_dir, rel_name),
+                            os.path.join(signature_dir, rel_dir, rel_name) + '.sig',
+                            privkey_name, cert_name)
+
+def sign_image_efi(image_name, signature_name, privkey_name, cert_name):
+    print('Should sign image %s with %s/%s and detach signature as %s' %
+          (image_name, privkey_name, cert_name, signature_name))
+
+def sign(config_name, imageversion_str, modules_privkey_name, modules_cert_name,
+         image_privkey_name, image_cert_name):
+    config = ConfigCoreDump(fp=open(config_name, 'rb'))
+    assert config['version',]['source'] == imageversion_str
+    abiname = config['version',]['abiname']
+    imageversion = VersionLinux(imageversion_str)
+
+    signature_dir = 'debian/signatures'
+    if os.path.isdir(signature_dir):
+        shutil.rmtree(signature_dir)
+
+    for arch in iter(config['base', ]['arches']):
+        for featureset in config['base', arch].get('featuresets', ()):
+            if not config.merge('base', None, featureset).get('enabled', True):
+                continue
+
+            for flavour in config['base', arch, featureset]['flavours']:
+                if not (config.merge('build', arch, featureset, flavour)
+                        .get('signed-modules', False)):
+                    continue
+
+                kernelversion = '%s%s-%s' % \
+                    (abiname,
+                     '' if featureset == 'none' else '-' + featureset,
+                     flavour)
+                package_name = 'linux-image-' + kernelversion
+
+                package_dir = get_package(package_name, imageversion, arch)
+
+                signature_dir = os.path.join('debian/signatures', package_name)
+                os.makedirs(signature_dir)
+                sign_modules('%s/lib/modules/%s' % (package_dir, kernelversion),
+                             '%s/lib/modules/%s' % (signature_dir, kernelversion),
+                             modules_privkey_name, modules_cert_name)
+
+                # Currently we can only sign kernel images built with an
+                # EFI stub, which has space for an embedded signature.
+                with open(os.path.join(package_dir,
+                                       'boot/config-%s' % kernelversion)) \
+                     as kconfig:
+                    if 'CONFIG_EFI_STUB=y\n' in kconfig:
+                        sign_image_efi('%s/boot/vmlinuz-%s' %
+                                       (package_dir, kernelversion),
+                                       '%s/boot/vmlinuz-%s.sig' %
+                                       (signature_dir, kernelversion),
+                                       image_privkey_name,
+                                       image_cert_name)
+
+    print('Signatures should be committed: git add debian/signatures && git commit')
+
+if __name__ == '__main__':
+    sign(sys.argv[1] + "/config.defines.dump", *sys.argv[2:])
diff --git a/debian/rules b/debian/rules
index b2439ed..683359e 100755
--- a/debian/rules
+++ b/debian/rules
@@ -4,6 +4,7 @@ SHELL := sh -e
 include debian/rules.defs
 
 GENCONTROL = debian/bin/gencontrol.py
+SIGN = debian/bin/sign.py
 
 DEB_HOST_ARCH  := $(shell dpkg-architecture -qDEB_HOST_ARCH)
 DEB_BUILD_ARCH := $(shell dpkg-architecture -qDEB_BUILD_ARCH)
@@ -60,9 +61,12 @@ binary-arch-all: debian/control $(BUILD_DIR)
 	$(MAKE) -f debian/rules.gen binary-arch
 
 maintainerclean: clean
-	rm -f debian/control debian/control.md5sum debian/rules.gen debian/*.bug-presubj
+	rm -rf debian/control debian/control.md5sum debian/rules.gen debian/*.bug-presubj debian/localpackages
 # dh_clean won't deal with binary packages that no longer exist after
 # removal of a flavour.
 	rm -rf $(filter-out %.config %.postinst %.templates %.NEWS, $(wildcard debian/linux-*))
 
-.PHONY: build build-arch build-indep clean binary binary-arch binary-indep binary-arch-all maintainerclean
+sign:
+	$(SIGN) /usr/src/linux-support-$(KERNEL_ABINAME) "$(KERNEL_IMAGE_VERSION)" "$(KERNEL_MODULES_PRIVKEY)" "$(KERNEL_MODULES_CERT)" "$(KERNEL_IMAGE_PRIVKEY)" "$(KERNEL_IMAGE_CERT)"
+
+.PHONY: build build-arch build-indep clean binary binary-arch binary-indep binary-arch-all maintainerclean sign
diff --git a/debian/rules.defs b/debian/rules.defs
index 2239bcc..4c20a16 100644
--- a/debian/rules.defs
+++ b/debian/rules.defs
@@ -3,3 +3,10 @@ STAMPS_DIR = debian/stamps
 TEMPLATES_DIR = debian/templates
 KERNEL_ABINAME := 4.5.0-trunk
 KERNEL_IMAGE_VERSION := 4.5-1~exp2
+
+# For initial testing - to be replaced with HSM
+KERNEL_SIGNER := benh at debian.org
+KERNEL_MODULES_PRIVKEY := $(HOME)/.linux-modules-$(KERNEL_SIGNER).key.priv.pem
+KERNEL_MODULES_CERT = debian/certs/linux-modules-$(KERNEL_SIGNER).cert.pem
+KERNEL_IMAGE_PRIVKEY := $(HOME)/.linux-image-$(KERNEL_SIGNER).key.priv.pem
+KERNEL_IMAGE_CERT := debian/certs/linux-image-$(KERNEL_SIGNER).cert.pem
diff --git a/debian/rules.real b/debian/rules.real
index 339bd00..963912c 100644
--- a/debian/rules.real
+++ b/debian/rules.real
@@ -1,5 +1,7 @@
 SHELL := bash -e
 
+include debian/rules.defs
+
 build-indep:
 
 install-signed: DH_OPTIONS = -p$(PACKAGE_NAME)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux-signed.git



More information about the Kernel-svn-changes mailing list