Merge ~xnox/ubuntu/+source/shim-signed:dualsigned into ubuntu/+source/shim-signed:ubuntu/devel

Proposed by Dimitri John Ledkov
Status: Needs review
Proposed branch: ~xnox/ubuntu/+source/shim-signed:dualsigned
Merge into: ubuntu/+source/shim-signed:ubuntu/devel
Diff against target: 286 lines (+240/-1)
5 files modified
CanonicalMasterCA.crt (+25/-0)
Makefile (+24/-1)
debian/changelog (+7/-0)
debian/shim-signed.install (+1/-0)
download-signed (+183/-0)
Reviewer Review Type Date Requested Status
Canonical Signing Pending
git-ubuntu developers Pending
Review via email: mp+386190@code.launchpad.net

Commit message

* Add download-signed script from linux-signed package
* Construct and ship dual-signed shim.

This depends on src:shim-canonical, until src:shim itself submits things for signing.

Also to be used by UC20 signing archive.

To post a comment you must log in.
2119b24... by Dimitri John Ledkov

releasing package shim-signed version 1.40.4

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Tested against a shim-canonical uploaded into a ppa, and side-replacing the Canonical CA cert with the PPA cert.

Unmerged commits

2119b24... by Dimitri John Ledkov

releasing package shim-signed version 1.40.4

738affe... by Dimitri John Ledkov

Construct and ship dual-signed shim.

9d2c974... by Dimitri John Ledkov

Add download-signed script from linux-signed package

6c5eb87... by Julian Andres Klode

1.40.3 (patches unapplied)

Imported using git-ubuntu import.

aa52aa1... by Julian Andres Klode

1.40.2 (patches unapplied)

Imported using git-ubuntu import.

275ab49... by Julian Andres Klode

1.40.1 (patches unapplied)

Imported using git-ubuntu import.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/CanonicalMasterCA.crt b/CanonicalMasterCA.crt
0new file mode 1006440new file mode 100644
index 0000000..55c06d5
--- /dev/null
+++ b/CanonicalMasterCA.crt
@@ -0,0 +1,25 @@
1-----BEGIN CERTIFICATE-----
2MIIENDCCAxygAwIBAgIJALlBJKAYLJJnMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYD
3VQQGEwJHQjEUMBIGA1UECAwLSXNsZSBvZiBNYW4xEDAOBgNVBAcMB0RvdWdsYXMx
4FzAVBgNVBAoMDkNhbm9uaWNhbCBMdGQuMTQwMgYDVQQDDCtDYW5vbmljYWwgTHRk
5LiBNYXN0ZXIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEyMDQxMjExMTI1MVoX
6DTQyMDQxMTExMTI1MVowgYQxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9m
7IE1hbjEQMA4GA1UEBwwHRG91Z2xhczEXMBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4x
8NDAyBgNVBAMMK0Nhbm9uaWNhbCBMdGQuIE1hc3RlciBDZXJ0aWZpY2F0ZSBBdXRo
9b3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/WzoWdO4hXa5h
107Z1WrL3e3nLz3X4tTGIPrMBtSAgRz42L+2EfJ8wRbtlVPTlU60A7sbvihTR5yvd7
11v7p6yBAtGX2tWc+m1OlOD9quUupMnpDOxpkNTmdleF350dU4Skp6j5OcfxqjhdvO
12+ov3wqIhLZtUQTUQVxONbLwpBlBKfuqZqWinO8cHGzKeoBmHDnm7aJktfpNS5fbr
13yZv5K+24aEm82ZVQQFvFsnGq61xX3nH5QArdW6wehC1QGlLW4fNrbpBkT1u06yDk
14YRDaWvDq5ELXAcT+IR/ZucBUlUKBUnIfSWR6yGwk8QhwC02loDLRoBxXqE3jr6WO
15BQU+EEOhAgMBAAGjgaYwgaMwHQYDVR0OBBYEFK2RmQvCKrH1FwSMI7ZlWiaONFpj
16MB8GA1UdIwQYMBaAFK2RmQvCKrH1FwSMI7ZlWiaONFpjMA8GA1UdEwEB/wQFMAMB
17Af8wCwYDVR0PBAQDAgGGMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly93d3cuY2Fu
18b25pY2FsLmNvbS9zZWN1cmUtYm9vdC1tYXN0ZXItY2EuY3JsMA0GCSqGSIb3DQEB
19CwUAA4IBAQA/ffZ2pbODtCt60G1SGgODxBKnUJxHkszAlHeC0q5Xs5kE9TI6xlUd
20B9sSqVb62NR2IOvkw1Hbmlyckj8Yc9qUaqGZOIykiG3B/Dlx0HR2FgM+ViM11VVH
21WxodQcLTEkzc/64KkpxiChcBnHPgXrH9vNa1GRF6fs0+A35m21uoyTlIUf9T4Zwx
22U5EbOxB1Axe65oECgJRwTEa3lLA9Fc0fjgLgaAKP+/lHHX2iAcYHUcSazO3dz6Nd
237ZK7vtH95uwfM1FzBL48crB9CPgB/5h9y5zgaTl3JUdxiLGNJ6UuqPc/X4Bplz6p
249JkU284DDgtmxBxtvbgnd8FClL38agq8
25-----END CERTIFICATE-----
diff --git a/Makefile b/Makefile
index 2a5395d..8ee5c6c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,5 @@
1SHIM_CANONICAL_VERSION=$(shell dpkg-query -W -f'$${Version}' shim-canonical-unsigned)
2
1check:3check:
2 mkdir -p build4 mkdir -p build
3 # Verifying that the image is signed with the correct key.5 # Verifying that the image is signed with the correct key.
@@ -8,6 +10,27 @@ check:
8 cp /usr/lib/shim/$(SHIM_BASE) build/$(SHIM_BASE).signed10 cp /usr/lib/shim/$(SHIM_BASE) build/$(SHIM_BASE).signed
9 sbattach --attach build/detached-sig build/$(SHIM_BASE).signed11 sbattach --attach build/detached-sig build/$(SHIM_BASE).signed
10 cmp $(SHIM_BASE).signed build/$(SHIM_BASE).signed12 cmp $(SHIM_BASE).signed build/$(SHIM_BASE).signed
13 ####
14 # Construct dual-signed shim
15 ./download-signed shim-canonical-unsigned $(SHIM_CANONICAL_VERSION) shim-canonical signed
16 # Verify that the downloaded binary has signatures chained to Canonical Master CA
17 sbverify --cert CanonicalMasterCA.crt $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE).signed
18 # Detach Canonical signature
19 sbattach --detach $(SHIM_CANONICAL_VERSION)/detached-sig-canonical $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE).signed
20 rm $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE).signed
21 # Compare that shims are all the same now
22 cmp /usr/lib/shim/$(SHIM_BASE) $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE)
23 # Reattach Canonical signature
24 sbattach --attach $(SHIM_CANONICAL_VERSION)/detached-sig-canonical $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE)
25 # Verify that attachment worked
26 sbverify --cert CanonicalMasterCA.crt $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE)
27 # Attach Microsoft signature
28 sbattach --attach build/detached-sig $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE)
29 # Validate that this shim is now dualsigned
30 sbverify --list $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE)
31 sbverify --cert CanonicalMasterCA.crt $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE)
32 sbverify --cert MicCorUEFCA2011_2011-06-27.crt $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE)
33 cp $(SHIM_CANONICAL_VERSION)/$(SHIM_BASE) build/$(SHIM_BASE).dualsigned
1134
12clean:35clean:
13 rm -rf build boot.csv BOOT$(EFI_ARCH).CSV36 rm -rf build $(SHIM_CANONICAL_VERSION) $shim_boot.csv BOOT$(EFI_ARCH).CSV
diff --git a/debian/changelog b/debian/changelog
index 9e48f1c..d42af56 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
1shim-signed (1.40.4) groovy; urgency=medium
2
3 * Add download-signed script from linux-signed package
4 * Construct and ship dual-signed shim.
5
6 -- Dimitri John Ledkov <xnox@ubuntu.com> Mon, 22 Jun 2020 16:23:33 +0100
7
1shim-signed (1.40.3) focal; urgency=medium8shim-signed (1.40.3) focal; urgency=medium
29
3 * Depend on the correct version of grub-signed (LP: #1871895)10 * Depend on the correct version of grub-signed (LP: #1871895)
diff --git a/debian/shim-signed.install b/debian/shim-signed.install
index 046d911..93d4e26 100755
--- a/debian/shim-signed.install
+++ b/debian/shim-signed.install
@@ -1,6 +1,7 @@
1#! /usr/bin/dh-exec1#! /usr/bin/dh-exec
22
3${SHIM_BASE}.signed /usr/lib/shim3${SHIM_BASE}.signed /usr/lib/shim
4build/${SHIM_BASE}.dualsigned /usr/lib/shim
4openssl.cnf /usr/lib/shim/mok5openssl.cnf /usr/lib/shim/mok
5debian/source_shim-signed.py /usr/share/apport/package-hooks/6debian/source_shim-signed.py /usr/share/apport/package-hooks/
6update-secureboot-policy /usr/sbin/7update-secureboot-policy /usr/sbin/
diff --git a/download-signed b/download-signed
7new file mode 1007558new file mode 100755
index 0000000..0793696
--- /dev/null
+++ b/download-signed
@@ -0,0 +1,183 @@
1#! /usr/bin/python3
2
3import hashlib
4import argparse
5import os
6import re
7import sys
8import tarfile
9from urllib import request
10from urllib.error import HTTPError
11from urllib.parse import (
12 urlparse,
13 urlunparse,
14 )
15
16import apt
17
18# package_name: package containing the objects we signed
19# package_version: package version containing the objects we signed
20# src_package: source package name in dists
21# signed_type: 'signed' or 'uefi' schema in the url
22
23parser = argparse.ArgumentParser()
24parser.add_argument(
25 "package_name",
26 help="package containining the objects we signed")
27parser.add_argument(
28 "package_version",
29 help="package version containing the objects we signed, or 'current'")
30parser.add_argument(
31 "src_package",
32 help="source package name in dists")
33parser.add_argument(
34 "signed_type",
35 nargs='?',
36 default='signed',
37 help="subdirectory type in the url, 'signed' or 'uefi'")
38args = parser.parse_args()
39
40
41class SignedDownloader:
42 """Download a block of signed information from dists.
43
44 Find a block of signed information as published in dists/*/signed
45 and download the contents. Use the contained checksum files to
46 identify the members and to validate them once downloaded.
47 """
48
49 def __init__(self, package_name, package_version, src_package, signed_type='signed'):
50 self.package_name = package_name
51 self.package_version = package_version
52 self.src_package = src_package
53
54 # Find the package in the available archive repositories. Use a _binary_
55 # package name and version to locate the appropriate archive. Then use the
56 # URI there to look for and find the appropriate binary.
57 cache = apt.Cache()
58
59 self.package = None
60 if self.package_version == "current":
61 self.package = cache[package_name].candidate
62 else:
63 for version in cache[package_name].versions:
64 if version.version == self.package_version:
65 self.package = version
66 break
67
68 if not self.package:
69 raise KeyError("{0}: package version not found".format(self.package_name))
70
71 origin = self.package.origins[0]
72 pool_parsed = urlparse(self.package.uri)
73 self.package_dir = "%s/%s/%s/%s-%s/%s/" % (
74 origin.archive, 'main', signed_type,
75 self.src_package, self.package.architecture, self.package_version)
76
77 # Prepare the master url stem and pull out any username/password. If present
78 # replace the default opener with one which offers that password.
79 dists_parsed_master = list(pool_parsed)
80 if '@' in dists_parsed_master[1]:
81 (username_password, host) = pool_parsed[1].split('@', 1)
82 (username, password) = username_password.split(':', 1)
83
84 dists_parsed_master[1] = host
85
86 # Work out the authentication domain.
87 domain_parsed = [ dists_parsed_master[0], dists_parsed_master[1], '/', None, None, None ]
88 auth_uri = urlunparse(domain_parsed)
89
90 # create a password manager
91 password_mgr = request.HTTPPasswordMgrWithDefaultRealm()
92
93 # Add the username and password.
94 # If we knew the realm, we could use it instead of None.
95 password_mgr.add_password(None, auth_uri, username, password)
96
97 handler = request.HTTPBasicAuthHandler(password_mgr)
98
99 # create "opener" (OpenerDirector instance)
100 opener = request.build_opener(handler)
101
102 # Now all calls to urllib.request.urlopen use our opener.
103 request.install_opener(opener)
104
105 self.dists_parsed = dists_parsed_master
106
107 def download_one(self, member, filename, hash_factory=None):
108 directory = os.path.dirname(filename)
109 if not os.path.exists(directory):
110 os.makedirs(directory)
111
112 dists_parsed = list(self.dists_parsed)
113 dists_parsed[2] = re.sub(r"/pool/.*", "/dists/" + self.package_dir + \
114 member, dists_parsed[2])
115 dists_uri = urlunparse(dists_parsed)
116
117 print("Downloading %s ... " % dists_uri, end='')
118 sys.stdout.flush()
119 try:
120 with request.urlopen(dists_uri) as dists, open(filename, "wb") as out:
121 hashobj = None
122 if hash_factory:
123 hashobj = hash_factory()
124 for chunk in iter(lambda: dists.read(256 * 1024), b''):
125 if hashobj:
126 hashobj.update(chunk)
127 out.write(chunk)
128 checksum = True
129 if hashobj:
130 checksum = hashobj.hexdigest()
131 except HTTPError as e:
132 if e.code == 404:
133 print("not found")
134 else:
135 raise
136 else:
137 print("found")
138 return checksum
139 return None
140
141 def download(self, base):
142 """Download an entire signed result from dists."""
143
144 # Download the checksums and use that to download the contents.
145 sums = 'SHA256SUMS'
146 sums_local = os.path.join(base, self.package_version, sums)
147 if not self.download_one(sums, sums_local):
148 print('download-signed: {0}: not found'.format(sums))
149 sys.exit(1)
150
151 # Read the checksum file and download the files it mentions.
152 here = os.path.abspath(base)
153 with open(sums_local) as sfd:
154 for line in sfd:
155 line = line.strip()
156 (checksum_expected, member) = (line[0:64], line[66:])
157 filename = os.path.abspath(os.path.join(base, self.package_version, member))
158 if not filename.startswith(here):
159 print('download-signed: {0}: member outside output directory'.format(member))
160 sys.exit(1)
161
162 # Download and checksum this member.
163 checksum_actual = self.download_one(member, filename, hashlib.sha256)
164 if checksum_expected != checksum_actual:
165 print('download-signed: {0}: member checksum invalid'.format(member))
166 sys.exit(1)
167
168 # If this is a tarball result then extract it.
169 here = os.path.abspath(os.path.join(base, self.package_version))
170 tarball_filename = os.path.join(base, self.package_version, 'signed.tar.gz')
171 if os.path.exists(tarball_filename):
172 with tarfile.open(tarball_filename) as tarball:
173 for tarinfo in tarball:
174 if not filename.startswith(here):
175 print('download-signed: {0}: tarball member outside output directory'.format(member))
176 sys.exit(1)
177 for tarinfo in tarball:
178 print('Extracting {0} ...'.format(tarinfo.name))
179 tarball.extract(tarinfo, base)
180
181
182downloader = SignedDownloader(**vars(args))
183downloader.download('.')

Subscribers

People subscribed via source and target branches