[linux-signed] 01/02: debian/bin/sign.py: Download detached signatures from the archive

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Sun Apr 16 18:31:13 UTC 2017


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

benh pushed a commit to branch benh/byhand-code-sign
in repository linux-signed.

commit 3eedbaee1fde806fa7c559531d1dc5c040491c4a
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Thu Jun 30 17:46:44 2016 +0200

    debian/bin/sign.py: Download detached signatures from the archive
---
 debian/.gitignore    |   1 -
 debian/README.source |  66 ++++++-------------
 debian/bin/sign.py   | 180 ++++++++-------------------------------------------
 debian/changelog     |   6 ++
 debian/rules         |   4 +-
 debian/rules.defs    |   7 --
 debian/rules.real    |   2 +-
 7 files changed, 57 insertions(+), 209 deletions(-)

diff --git a/debian/.gitignore b/debian/.gitignore
index 57e286a..c67af41 100644
--- a/debian/.gitignore
+++ b/debian/.gitignore
@@ -7,7 +7,6 @@
 /control*
 /files
 /linux-image-*
-/localpackages/
 /rules.gen
 /source.lintian-overrides
 /stamps/
diff --git a/debian/README.source b/debian/README.source
index 9a9b873..449537e 100644
--- a/debian/README.source
+++ b/debian/README.source
@@ -1,9 +1,13 @@
-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.
+This package must be updated along with the linux package:
 
-All signatures are made at source preparation time, not during a
-build.  This avoids the need to expose signing keys to buildds and
+1. Upload linux source package
+2. Build daemons upload linux binary packages and a tarball of code to
+   be signed
+3. Debian archive software generates detached signatures for the code
+4. Download signature tarballs and update this source package
+5. Upload linux-signed source package
+
+This process avoids the need to expose signing keys to buildds and
 allows reproducible builds.
 
 When preparing a source package, you will need python3-debian,
@@ -11,57 +15,27 @@ 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:
+To update the signatures:
 
-1. Uupdate debian/rules.defs:
+1. Update 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.
-   - MIRROR_SUITE: Suite from which to download the linux-image
-     packages, if they are not already provided in
-     debian/localpackages.
-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'
-
-You may see these warnings when signing a kernel image:
-
-    warning: file-aligned section .text extends beyond end of file
-    warning: checksum areas are greater than image size. Invalid section table?
-
-This is harmless in practice - sbsign will insert padding to fix it up.
+   - MIRROR_URL: Base URL of the mirror from which to download the
+     signature tarballs
+   - MIRROR_SUITE: Suite from which to download the signature tarballs
+2. Run 'debian/rules sign'
 
 Then, to prepare the source package:
 
-4. Run 'debian/rules maintainerclean'
-5. Update debian/rules.defs:
+3. Run 'debian/rules maintainerclean'
+4. Update debian/rules.defs:
    - SIGNED_VERSION_SUFFIX: In case a new source upload is made
      without changing KERNEL_IMAGE_VERSION, this suffix may be set
      to e.g. +s2, +s3, etc. to distinguish the binary versions.
      Normally it should be empty.
-6. Run 'debian/rules debian/control'
-7. Run 'dpkg-buildpackage -uc -us -S -d'
+5. Run 'debian/rules debian/control'
+6. Run 'dpkg-buildpackage -uc -us -S -d'
 
- -- Ben Hutchings <ben at decadent.org.uk>, Sun, 26 Jun 2016 15:07:55 +0200
+ -- Ben Hutchings <ben at decadent.org.uk>, Wed, 29 Jun 2016 17:13:35 +0200
diff --git a/debian/bin/sign.py b/debian/bin/sign.py
index 5ac3848..b803c5c 100755
--- a/debian/bin/sign.py
+++ b/debian/bin/sign.py
@@ -13,9 +13,6 @@ from debian_linux.debian import VersionLinux
 class ArchiveMetadataError(Exception):
     pass
 
-class MissingPackageError(Exception):
-    pass
-
 _release_data = {}
 
 def get_release_data(mirror, suite):
@@ -60,118 +57,38 @@ def get_release_data(mirror, suite):
 
     return _release_data[(mirror, suite)]
 
-_packages_data = {}
+def get_tarball(mirror, suite, name, version, arch):
+    tarball_basename = '%s_%s_%s_sigs.tar.xz' % (name, version, arch)
+    tarball_dir = 'debian/build'
+    tarball_file = os.path.join(tarball_dir, tarball_basename)
+    path = os.path.join('main/code-sign', tarball_basename)
 
-def get_packages_data(mirror, suite, arch):
-    if (mirror, suite, arch) not in _packages_data:
-        release_data = get_release_data(mirror, suite)
+    os.makedirs(tarball_dir, exist_ok=True)
 
-        path = 'main/binary-%s/Packages.xz' % arch
+    if not os.path.isfile(tarball_file):
+        release_data = get_release_data(mirror, suite)
         file_data = release_data[path]
-        url = urllib.parse.urljoin(mirror, 'dists/%s/%s' % (suite, path))
+        url = urllib.parse.urljoin(
+            urllib.parse.urljoin(
+                urllib.parse.urljoin(mirror, 'dists/'), suite + '/'), path)
         print('I: Fetching %s' % url)
         with urllib.request.urlopen(url) as req:
-            packages_raw = req.read()
+            tarball = req.read()
 
         # Validate against Release file
-        if len(packages_raw) != int(file_data['size']):
-            raise ArchiveMetadataError('%s has wrong size' % url)
+        if len(tarball) != int(file_data['Size']):
+            raise Exception('%s has wrong size' % url)
         h = hashlib.sha256()
-        h.update(packages_raw)
-        if h.digest() != bytes.fromhex(file_data['sha256']):
-            raise ArchiveMetadataError('%s has wrong checksum' % url)
-
-        packages_stream = io.TextIOWrapper(
-            io.BytesIO(lzma.decompress(packages_raw)), 'utf-8')
-
-        # Make a dictionary of per-package data
-        _packages_data[(mirror, suite, arch)] = data = {}
-        for package_data in deb822.Packages.iter_paragraphs(packages_stream):
-            name = package_data['Package']
-            # Filter so the heap doesn't become huge
-            if name.startswith('linux-image-'):
-                data[name] = package_data
-
-    return _packages_data[(mirror, suite, arch)]
-
-def get_package(mirror, suite, 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)
-
-    os.makedirs(packages_dir, exist_ok=True)
-
-    if not os.path.isfile(package_file):
-        packages_data = get_packages_data(mirror, suite, arch)
-        if name not in packages_data:
-            raise MissingPackageError('package %s is not available' % name)
-        package_data = packages_data[name]
-        if package_data['Version'] != version:
-            raise MissingPackageError(
-                'package %s version %s is not available; only version %s' %
-                (name, version, package_data['Version']))
-        url = urllib.parse.urljoin(mirror, package_data['Filename'])
-        print('I: Fetching %s' % url)
-        with urllib.request.urlopen(url) as req:
-            package = req.read()
+        h.update(tarball)
+        if h.digest() != bytes.fromhex(file_data['SHA256']):
+            raise Exception('%s has wrong checksum' % url)
 
-        # Validate against Packages file
-        if len(package) != int(package_data['Size']):
-            raise ArchiveMetadataError('%s has wrong size' % url)
-        h = hashlib.sha256()
-        h.update(package)
-        if h.digest() != bytes.fromhex(package_data['SHA256']):
-            raise ArchiveMetadataError('%s has wrong checksum' % url)
-
-        with open(package_file, 'wb') as f:
-            f.write(package)
-
-    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)
-        subprocess.check_call(['dpkg-deb', '-x', package_file, unpack_temp_dir])
-        os.rename(unpack_temp_dir, unpack_dir)
-
-    return unpack_dir
-
-def sign_module(kbuild_dir, module_name, signature_name, privkey_name,
-                cert_name):
-    os.makedirs(os.path.dirname(signature_name), exist_ok=True)
-    # 'sign-file -d' currently ignores any <dest> argument and always writes
-    # to <module>.p7s, so accept that and rename afterwards
-    subprocess.check_call(['%s/scripts/sign-file' % kbuild_dir, '-d',
-                           'sha256', privkey_name, cert_name, module_name])
-    os.rename(module_name + '.p7s', signature_name)
-
-def sign_modules(kbuild_dir, modules_dir, signature_dir, privkey_name,
-                 cert_name):
-    print('I: Signing modules in %s' % modules_dir)
-    print('I: Storing detached signatures in %s' % signature_dir)
-    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(kbuild_dir,
-                            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('I: Signing image %s' % image_name)
-    print('I: Storing detached signature as %s' % signature_name)
-    os.makedirs(os.path.dirname(signature_name), exist_ok=True)
-    subprocess.check_call(['sbsign', '--key', privkey_name, '--cert', cert_name,
-                           '--detached', '--output', signature_name, image_name])
-    # Work around bug #819987
-    if not os.path.isfile(signature_name):
-        raise Exception('sbsign failed')
-
-def sign(config_name, imageversion_str, modules_privkey_name, modules_cert_name,
-         image_privkey_name, image_cert_name, mirror_url, suite):
+        with open(tarball_file, 'wb') as f:
+            f.write(tarball)
+
+    subprocess.check_call(['tar', '-C', 'debian/signatures', '-xaf', tarball_file])
+
+def sign(config_name, imageversion_str, mirror_url, suite):
     config = ConfigCoreDump(fp=open(config_name, 'rb'))
 
     # Check current linux-support version
@@ -184,55 +101,14 @@ def sign(config_name, imageversion_str, modules_privkey_name, modules_cert_name,
     signature_dir = 'debian/signatures'
     if os.path.isdir(signature_dir):
         shutil.rmtree(signature_dir)
+    os.makedirs('debian/signatures')
 
     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-%s-unsigned' % kernelversion
-
-                try:
-                    package_dir = get_package(mirror_url, suite,
-                                              package_name, imageversion_str, arch)
-                except MissingPackageError:
-                    package_dir = get_package(
-                        'http://incoming.debian.org/debian-buildd/',
-                        'buildd-' + suite,
-                        package_name, imageversion_str, arch)
-
-                # Shrink the heap before we start forking children
-                gc.collect()
-
-                signature_dir = os.path.join('debian/signatures', package_name)
-                os.makedirs(signature_dir)
-                sign_modules(kbuild_dir,
-                             '%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_file:
-                    kconfig = kconfig_file.readlines()
-                if ('CONFIG_EFI_STUB=y\n' in kconfig and
-                    'CONFIG_EFI_SECURE_BOOT_SECURELEVEL=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)
+            if (config.merge('base', None, featureset).get('enabled', True) and
+                config.merge('build', arch, featureset).get('signed-modules', False)):
+                get_tarball(mirror_url, suite, 'linux-code-sign',
+                            imageversion_str, arch)
 
     print('Signatures should be committed: git add debian/signatures && git commit')
 
diff --git a/debian/changelog b/debian/changelog
index 38704a1..d7b6827 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+linux-signed (4.5) UNRELEASED; urgency=medium
+
+  * debian/bin/sign.py: Download detached signatures from the archive
+
+ -- Ben Hutchings <ben at decadent.org.uk>  Sun, 16 Apr 2017 19:22:17 +0100
+
 linux-signed (4.4) unstable; urgency=medium
 
   * Update to linux version 4.9.18-1
diff --git a/debian/rules b/debian/rules
index f960b3e..ae2af5a 100755
--- a/debian/rules
+++ b/debian/rules
@@ -62,9 +62,9 @@ binary-arch-all: debian/control $(BUILD_DIR)
 	$(MAKE) -f debian/rules.gen binary-arch
 
 maintainerclean:
-	rm -rf debian/control debian/control.md5sum debian/linux-* debian/rules.gen debian/localpackages debian/*-modules-*-di* debian/kernel-image-*-di*
+	rm -rf debian/control debian/control.md5sum debian/linux-* debian/rules.gen debian/*-modules-*-di* debian/kernel-image-*-di*
 
 sign:
-	$(SIGN) /usr/src/linux-support-$(KERNEL_ABINAME) "$(KERNEL_IMAGE_VERSION)" "$(KERNEL_MODULES_PRIVKEY)" "$(KERNEL_MODULES_CERT)" "$(KERNEL_IMAGE_PRIVKEY)" "$(KERNEL_IMAGE_CERT)" "$(MIRROR_URL)" "$(MIRROR_SUITE)"
+	$(SIGN) /usr/src/linux-support-$(KERNEL_ABINAME) "$(KERNEL_IMAGE_VERSION)" "$(MIRROR_URL)" "$(MIRROR_SUITE)"
 
 .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 6bc82f2..ffd894f 100644
--- a/debian/rules.defs
+++ b/debian/rules.defs
@@ -8,10 +8,3 @@ SIGNED_VERSION_SUFFIX :=
 
 MIRROR_URL = http://deb.debian.org/debian/
 MIRROR_SUITE = unstable
-
-# 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 8632121..3e4998c 100644
--- a/debian/rules.real
+++ b/debian/rules.real
@@ -28,7 +28,7 @@ install-signed:
 	while read path; do \
 		/usr/lib/linux-kbuild-$(VERSION)/scripts/sign-file -s \
 			$(SIGNATURE_DIR)/lib/modules/$(KERNEL_VERSION)/$$path \
-			sha256 $(KERNEL_MODULES_CERT) \
+			sha256 dummy \
 			$(PACKAGE_DIR)/lib/modules/$(KERNEL_VERSION)/$${path%.sig}; \
 	done < <(find $(SIGNATURE_DIR)/lib/modules/$(KERNEL_VERSION) -name '*.sig' -printf '%P\n')
 # Copy any device tree files

-- 
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