Merge lp:~apw/launchpad/signing-fit into lp:launchpad

Proposed by Andy Whitcroft
Status: Superseded
Proposed branch: lp:~apw/launchpad/signing-fit
Merge into: lp:launchpad
Diff against target: 876 lines (+442/-35)
2 files modified
lib/lp/archivepublisher/signing.py (+81/-26)
lib/lp/archivepublisher/tests/test_signing.py (+361/-9)
To merge this branch: bzr merge lp:~apw/launchpad/signing-fit
Reviewer Review Type Date Requested Status
Launchpad code reviewers Pending
Review via email: mp+368276@code.launchpad.net

This proposal has been superseded by a proposal from 2019-06-03.

Commit message

Add u-boot Flat Image Tree signing support. u-boot supports generation and verification of FIT images in a similar fashion to secure boot. These signatures are expressed as signature nodes in the DTB contained within the FIT image. Add support for performing FIT signing against *.fit files in the signing custom uploads.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/archivepublisher/signing.py'
--- lib/lp/archivepublisher/signing.py 2018-08-03 16:10:41 +0000
+++ lib/lp/archivepublisher/signing.py 2019-06-03 14:59:55 +0000
@@ -95,6 +95,10 @@
95 self.kmod_x509 = None95 self.kmod_x509 = None
96 self.opal_pem = None96 self.opal_pem = None
97 self.opal_x509 = None97 self.opal_x509 = None
98 self.sipl_pem = None
99 self.sipl_x509 = None
100 self.fit_key = None
101 self.fit_cert = None
98 self.autokey = False102 self.autokey = False
99 else:103 else:
100 self.uefi_key = os.path.join(pubconf.signingroot, "uefi.key")104 self.uefi_key = os.path.join(pubconf.signingroot, "uefi.key")
@@ -103,6 +107,13 @@
103 self.kmod_x509 = os.path.join(pubconf.signingroot, "kmod.x509")107 self.kmod_x509 = os.path.join(pubconf.signingroot, "kmod.x509")
104 self.opal_pem = os.path.join(pubconf.signingroot, "opal.pem")108 self.opal_pem = os.path.join(pubconf.signingroot, "opal.pem")
105 self.opal_x509 = os.path.join(pubconf.signingroot, "opal.x509")109 self.opal_x509 = os.path.join(pubconf.signingroot, "opal.x509")
110 self.sipl_pem = os.path.join(pubconf.signingroot, "sipl.pem")
111 self.sipl_x509 = os.path.join(pubconf.signingroot, "sipl.x509")
112 # Note: the signature tool allows a collection of keys and takes
113 # a directory name with all valid keys. Avoid mixing the
114 # other signing types' keys with the fit keys.
115 self.fit_key = os.path.join(pubconf.signingroot, "fit", "fit.key")
116 self.fit_cert = os.path.join(pubconf.signingroot, "fit", "fit.crt")
106 self.autokey = pubconf.signingautokey117 self.autokey = pubconf.signingautokey
107118
108 self.setComponents(tarfile_path)119 self.setComponents(tarfile_path)
@@ -176,6 +187,10 @@
176 yield (os.path.join(dirpath, filename), self.signKmod)187 yield (os.path.join(dirpath, filename), self.signKmod)
177 elif filename.endswith(".opal"):188 elif filename.endswith(".opal"):
178 yield (os.path.join(dirpath, filename), self.signOpal)189 yield (os.path.join(dirpath, filename), self.signOpal)
190 elif filename.endswith(".sipl"):
191 yield (os.path.join(dirpath, filename), self.signSipl)
192 elif filename.endswith(".fit"):
193 yield (os.path.join(dirpath, filename), self.signFit)
179194
180 def getKeys(self, which, generate, *keynames):195 def getKeys(self, which, generate, *keynames):
181 """Validate and return the uefi key and cert for encryption."""196 """Validate and return the uefi key and cert for encryption."""
@@ -207,29 +222,33 @@
207 common_name = "PPA %s %s" % (owner, archive)222 common_name = "PPA %s %s" % (owner, archive)
208 return common_name[0:64 - len(suffix)] + suffix223 return common_name[0:64 - len(suffix)] + suffix
209224
210 def generateUefiKeys(self):225 def generateKeyCrtPair(self, key_type, key_filename, cert_filename):
211 """Generate new UEFI Keys for this archive."""226 """Generate new Key/Crt key pairs."""
212 directory = os.path.dirname(self.uefi_key)227 directory = os.path.dirname(key_filename)
213 if not os.path.exists(directory):228 if not os.path.exists(directory):
214 os.makedirs(directory)229 os.makedirs(directory)
215230
216 common_name = self.generateKeyCommonName(231 common_name = self.generateKeyCommonName(
217 self.archive.owner.name, self.archive.name)232 self.archive.owner.name, self.archive.name, key_type)
218 subject = '/CN=' + common_name + '/'233 subject = '/CN=' + common_name + '/'
219234
220 old_mask = os.umask(0o077)235 old_mask = os.umask(0o077)
221 try:236 try:
222 new_key_cmd = [237 new_key_cmd = [
223 'openssl', 'req', '-new', '-x509', '-newkey', 'rsa:2048',238 'openssl', 'req', '-new', '-x509', '-newkey', 'rsa:2048',
224 '-subj', subject, '-keyout', self.uefi_key,239 '-subj', subject, '-keyout', key_filename,
225 '-out', self.uefi_cert, '-days', '3650', '-nodes', '-sha256',240 '-out', cert_filename, '-days', '3650', '-nodes', '-sha256',
226 ]241 ]
227 self.callLog("UEFI keygen", new_key_cmd)242 self.callLog(key_type + " keygen", new_key_cmd)
228 finally:243 finally:
229 os.umask(old_mask)244 os.umask(old_mask)
230245
231 if os.path.exists(self.uefi_cert):246 if os.path.exists(cert_filename):
232 os.chmod(self.uefi_cert, 0o644)247 os.chmod(cert_filename, 0o644)
248
249 def generateUefiKeys(self):
250 """Generate new UEFI Keys for this archive."""
251 self.generateKeyCrtPair("UEFI", self.uefi_key, self.uefi_cert)
233252
234 def signUefi(self, image):253 def signUefi(self, image):
235 """Attempt to sign an image."""254 """Attempt to sign an image."""
@@ -242,7 +261,7 @@
242 cmdl = ["sbsign", "--key", key, "--cert", cert, image]261 cmdl = ["sbsign", "--key", key, "--cert", cert, image]
243 return self.callLog("UEFI signing", cmdl)262 return self.callLog("UEFI signing", cmdl)
244263
245 openssl_config_opal = textwrap.dedent("""264 openssl_config_base = textwrap.dedent("""
246 [ req ]265 [ req ]
247 default_bits = 4096266 default_bits = 4096
248 distinguished_name = req_distinguished_name267 distinguished_name = req_distinguished_name
@@ -260,37 +279,35 @@
260 authorityKeyIdentifier=keyid279 authorityKeyIdentifier=keyid
261 """)280 """)
262281
263 openssl_config_kmod = openssl_config_opal + textwrap.dedent("""282 openssl_config_opal = "# OPAL openssl config" + openssl_config_base
283
284 openssl_config_kmod = "# KMOD openssl config" + openssl_config_base + \
285 textwrap.dedent("""
264 # codeSigning: specifies that this key is used to sign code.286 # codeSigning: specifies that this key is used to sign code.
265 # 1.3.6.1.4.1.2312.16.1.2: defines this key as used for287 # 1.3.6.1.4.1.2312.16.1.2: defines this key as used for
266 # module signing only. See https://lkml.org/lkml/2015/8/26/741.288 # module signing only. See https://lkml.org/lkml/2015/8/26/741.
267 extendedKeyUsage = codeSigning,1.3.6.1.4.1.2312.16.1.2289 extendedKeyUsage = codeSigning,1.3.6.1.4.1.2312.16.1.2
268 """)290 """)
269291
270 def generateOpensslConfig(self, key_type, common_name):292 openssl_config_sipl = "# SIPL openssl config" + openssl_config_base
271 if key_type == 'Kmod':293
272 genkey_tmpl = self.openssl_config_kmod294 def generateOpensslConfig(self, key_type, genkey_tmpl):
273 elif key_type == 'Opal':295 # Truncate name to 64 character maximum.
274 genkey_tmpl = self.openssl_config_opal296 common_name = self.generateKeyCommonName(
275 else:297 self.archive.owner.name, self.archive.name, key_type)
276 raise ValueError("unknown key_type " + key_type)
277298
278 return genkey_tmpl.format(common_name=common_name)299 return genkey_tmpl.format(common_name=common_name)
279300
280 def generatePemX509Pair(self, key_type, pem_filename, x509_filename):301 def generatePemX509Pair(self, key_type, genkey_text, pem_filename,
302 x509_filename):
281 """Generate new pem/x509 key pairs."""303 """Generate new pem/x509 key pairs."""
282 directory = os.path.dirname(pem_filename)304 directory = os.path.dirname(pem_filename)
283 if not os.path.exists(directory):305 if not os.path.exists(directory):
284 os.makedirs(directory)306 os.makedirs(directory)
285307
286 # Truncate name to 64 character maximum.
287 common_name = self.generateKeyCommonName(
288 self.archive.owner.name, self.archive.name, key_type)
289
290 old_mask = os.umask(0o077)308 old_mask = os.umask(0o077)
291 try:309 try:
292 with tempfile.NamedTemporaryFile(suffix='.keygen') as tf:310 with tempfile.NamedTemporaryFile(suffix='.keygen') as tf:
293 genkey_text = self.generateOpensslConfig(key_type, common_name)
294 print(genkey_text, file=tf)311 print(genkey_text, file=tf)
295312
296 # Close out the underlying file so we know it is complete.313 # Close out the underlying file so we know it is complete.
@@ -318,7 +335,8 @@
318335
319 def generateKmodKeys(self):336 def generateKmodKeys(self):
320 """Generate new Kernel Signing Keys for this archive."""337 """Generate new Kernel Signing Keys for this archive."""
321 self.generatePemX509Pair("Kmod", self.kmod_pem, self.kmod_x509)338 config = self.generateOpensslConfig("Kmod", self.openssl_config_kmod)
339 self.generatePemX509Pair("Kmod", config, self.kmod_pem, self.kmod_x509)
322340
323 def signKmod(self, image):341 def signKmod(self, image):
324 """Attempt to sign a kernel module."""342 """Attempt to sign a kernel module."""
@@ -333,7 +351,8 @@
333351
334 def generateOpalKeys(self):352 def generateOpalKeys(self):
335 """Generate new Opal Signing Keys for this archive."""353 """Generate new Opal Signing Keys for this archive."""
336 self.generatePemX509Pair("Opal", self.opal_pem, self.opal_x509)354 config = self.generateOpensslConfig("Opal", self.openssl_config_opal)
355 self.generatePemX509Pair("Opal", config, self.opal_pem, self.opal_x509)
337356
338 def signOpal(self, image):357 def signOpal(self, image):
339 """Attempt to sign a kernel image for Opal."""358 """Attempt to sign a kernel image for Opal."""
@@ -346,6 +365,42 @@
346 cmdl = ["kmodsign", "-D", "sha512", pem, cert, image, image + ".sig"]365 cmdl = ["kmodsign", "-D", "sha512", pem, cert, image, image + ".sig"]
347 return self.callLog("Opal signing", cmdl)366 return self.callLog("Opal signing", cmdl)
348367
368 def generateSiplKeys(self):
369 """Generate new Sipl Signing Keys for this archive."""
370 config = self.generateOpensslConfig("Sipl", self.openssl_config_sipl)
371 self.generatePemX509Pair("Sipl", config, self.sipl_pem, self.sipl_x509)
372
373 def signSipl(self, image):
374 """Attempt to sign a kernel image for Sipl."""
375 remove_if_exists("%s.sig" % image)
376 (pem, cert) = self.getKeys('Sipl Kernel', self.generateSiplKeys,
377 self.sipl_pem, self.sipl_x509)
378 if not pem or not cert:
379 return
380 self.publishPublicKey(cert)
381 cmdl = ["kmodsign", "-D", "sha512", pem, cert, image, image + ".sig"]
382 return self.callLog("Sipl signing", cmdl)
383
384 def generateFitKeys(self):
385 """Generate new Fit Keys for this archive."""
386 self.generateKeyCrtPair("Fit", self.fit_key, self.fit_cert)
387
388 def signFit(self, image):
389 """Attempt to sign an image."""
390 image_signed = "%s.signed" % image
391 remove_if_exists(image_signed)
392 (key, cert) = self.getKeys('Fit', self.generateFitKeys,
393 self.fit_key, self.fit_cert)
394 if not key or not cert:
395 return
396 self.publishPublicKey(cert)
397 # Make a copy of the image as mkimage signs in place and in
398 # signed-only mode we will remove the original file.
399 shutil.copy(image, image_signed)
400 cmdl = ["mkimage", "-F", "-k", os.path.dirname(key), "-r",
401 image_signed]
402 return self.callLog("Fit signing", cmdl)
403
349 def convertToTarball(self):404 def convertToTarball(self):
350 """Convert unpacked output to signing tarball."""405 """Convert unpacked output to signing tarball."""
351 tarfilename = os.path.join(self.tmpdir, "signed.tar.gz")406 tarfilename = os.path.join(self.tmpdir, "signed.tar.gz")
352407
=== modified file 'lib/lp/archivepublisher/tests/test_signing.py'
--- lib/lp/archivepublisher/tests/test_signing.py 2019-05-24 11:10:38 +0000
+++ lib/lp/archivepublisher/tests/test_signing.py 2019-06-03 14:59:55 +0000
@@ -85,12 +85,17 @@
85 self.callers = {85 self.callers = {
86 "UEFI signing": 0,86 "UEFI signing": 0,
87 "UEFI keygen": 0,87 "UEFI keygen": 0,
88 "Fit signing": 0,
89 "Fit keygen": 0,
88 "Kmod signing": 0,90 "Kmod signing": 0,
89 "Kmod keygen key": 0,91 "Kmod keygen key": 0,
90 "Kmod keygen cert": 0,92 "Kmod keygen cert": 0,
91 "Opal signing": 0,93 "Opal signing": 0,
92 "Opal keygen key": 0,94 "Opal keygen key": 0,
93 "Opal keygen cert": 0,95 "Opal keygen cert": 0,
96 "Sipl signing": 0,
97 "Sipl keygen key": 0,
98 "Sipl keygen cert": 0,
94 }99 }
95100
96 def __call__(self, *args, **kwargs):101 def __call__(self, *args, **kwargs):
@@ -108,6 +113,15 @@
108 write_file(self.upload.uefi_key, b"")113 write_file(self.upload.uefi_key, b"")
109 write_file(self.upload.uefi_cert, b"")114 write_file(self.upload.uefi_cert, b"")
110115
116 elif description == "Fit signing":
117 filename = cmdl[-1]
118 if filename.endswith(".fit"):
119 write_file(filename + ".signed", b"")
120
121 elif description == "Fit keygen":
122 write_file(self.upload.fit_key, b"")
123 write_file(self.upload.fit_cert, b"")
124
111 elif description == "Kmod signing":125 elif description == "Kmod signing":
112 filename = cmdl[-1]126 filename = cmdl[-1]
113 if filename.endswith(".ko.sig"):127 if filename.endswith(".ko.sig"):
@@ -130,9 +144,20 @@
130 elif description == "Opal keygen key":144 elif description == "Opal keygen key":
131 write_file(self.upload.opal_pem, b"")145 write_file(self.upload.opal_pem, b"")
132146
147 elif description == "Sipl signing":
148 filename = cmdl[-1]
149 if filename.endswith(".sipl.sig"):
150 write_file(filename, b"")
151
152 elif description == "Sipl keygen cert":
153 write_file(self.upload.sipl_x509, b"")
154
155 elif description == "Sipl keygen key":
156 write_file(self.upload.sipl_pem, b"")
157
133 else:158 else:
134 raise AssertionError("unknown command executed cmd=(%s)" %159 raise AssertionError("unknown command executed description=(%s) "
135 " ".join(cmdl))160 "cmd=(%s)" % (description, " ".join(cmdl)))
136161
137 return 0162 return 0
138163
@@ -177,7 +202,7 @@
177 purpose=ArchivePurpose.PPA)202 purpose=ArchivePurpose.PPA)
178 self.signing_dir = os.path.join(203 self.signing_dir = os.path.join(
179 self.temp_dir, "signing", "signing-owner", "testing")204 self.temp_dir, "signing", "signing-owner", "testing")
180 self.testcase_cn = '/CN=PPA signing-owner testing/'205 self.testcase_cn = 'PPA signing-owner testing'
181 pubconf = getPubConfig(self.archive)206 pubconf = getPubConfig(self.archive)
182 if not os.path.exists(pubconf.temproot):207 if not os.path.exists(pubconf.temproot):
183 os.makedirs(pubconf.temproot)208 os.makedirs(pubconf.temproot)
@@ -197,6 +222,15 @@
197 write_file(self.key, b"")222 write_file(self.key, b"")
198 write_file(self.cert, b"")223 write_file(self.cert, b"")
199224
225 def setUpFitKeys(self, create=True):
226 # We expect and need the fit keys to be in their own
227 # directory as part of key protection for mkimage.
228 self.fit_key = os.path.join(self.signing_dir, "fit", "fit.key")
229 self.fit_cert = os.path.join(self.signing_dir, "fit", "fit.crt")
230 if create:
231 write_file(self.fit_key, b"")
232 write_file(self.fit_cert, b"")
233
200 def setUpKmodKeys(self, create=True):234 def setUpKmodKeys(self, create=True):
201 self.kmod_pem = os.path.join(self.signing_dir, "kmod.pem")235 self.kmod_pem = os.path.join(self.signing_dir, "kmod.pem")
202 self.kmod_x509 = os.path.join(self.signing_dir, "kmod.x509")236 self.kmod_x509 = os.path.join(self.signing_dir, "kmod.x509")
@@ -211,6 +245,13 @@
211 write_file(self.opal_pem, b"")245 write_file(self.opal_pem, b"")
212 write_file(self.opal_x509, b"")246 write_file(self.opal_x509, b"")
213247
248 def setUpSiplKeys(self, create=True):
249 self.sipl_pem = os.path.join(self.signing_dir, "sipl.pem")
250 self.sipl_x509 = os.path.join(self.signing_dir, "sipl.x509")
251 if create:
252 write_file(self.sipl_pem, b"")
253 write_file(self.sipl_x509, b"")
254
214 def openArchive(self, loader_type, version, arch):255 def openArchive(self, loader_type, version, arch):
215 self.path = os.path.join(256 self.path = os.path.join(
216 self.temp_dir, "%s_%s_%s.tar.gz" % (loader_type, version, arch))257 self.temp_dir, "%s_%s_%s.tar.gz" % (loader_type, version, arch))
@@ -234,6 +275,7 @@
234 upload = SigningUpload()275 upload = SigningUpload()
235 # Under no circumstances is it safe to execute actual commands.276 # Under no circumstances is it safe to execute actual commands.
236 self.fake_call = FakeMethod(result=0)277 self.fake_call = FakeMethod(result=0)
278 self.fake_copyfile = FakeMethod(result=0)
237 upload.callLog = FakeMethodCallLog(upload=upload)279 upload.callLog = FakeMethodCallLog(upload=upload)
238 self.useFixture(MonkeyPatch("subprocess.call", self.fake_call))280 self.useFixture(MonkeyPatch("subprocess.call", self.fake_call))
239 upload.process(self.archive, self.path, self.suite)281 upload.process(self.archive, self.path, self.suite)
@@ -247,6 +289,8 @@
247 upload.signUefi = FakeMethod()289 upload.signUefi = FakeMethod()
248 upload.signKmod = FakeMethod()290 upload.signKmod = FakeMethod()
249 upload.signOpal = FakeMethod()291 upload.signOpal = FakeMethod()
292 upload.signSipl = FakeMethod()
293 upload.signFit = FakeMethod()
250 # Under no circumstances is it safe to execute actual commands.294 # Under no circumstances is it safe to execute actual commands.
251 fake_call = FakeMethod(result=0)295 fake_call = FakeMethod(result=0)
252 self.useFixture(MonkeyPatch("subprocess.call", fake_call))296 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
@@ -267,6 +311,8 @@
267 self.tarfile.add_file("1.0/empty.efi", b"")311 self.tarfile.add_file("1.0/empty.efi", b"")
268 self.tarfile.add_file("1.0/empty.ko", b"")312 self.tarfile.add_file("1.0/empty.ko", b"")
269 self.tarfile.add_file("1.0/empty.opal", b"")313 self.tarfile.add_file("1.0/empty.opal", b"")
314 self.tarfile.add_file("1.0/empty.sipl", b"")
315 self.tarfile.add_file("1.0/empty.fit", b"")
270 upload = self.process_emulate()316 upload = self.process_emulate()
271 self.assertContentEqual([], upload.callLog.caller_list())317 self.assertContentEqual([], upload.callLog.caller_list())
272318
@@ -277,6 +323,8 @@
277 self.tarfile.add_file("1.0/empty.efi", b"")323 self.tarfile.add_file("1.0/empty.efi", b"")
278 self.tarfile.add_file("1.0/empty.ko", b"")324 self.tarfile.add_file("1.0/empty.ko", b"")
279 self.tarfile.add_file("1.0/empty.opal", b"")325 self.tarfile.add_file("1.0/empty.opal", b"")
326 self.tarfile.add_file("1.0/empty.sipl", b"")
327 self.tarfile.add_file("1.0/empty.fit", b"")
280 upload = self.process_emulate()328 upload = self.process_emulate()
281 self.assertContentEqual([], upload.callLog.caller_list())329 self.assertContentEqual([], upload.callLog.caller_list())
282330
@@ -289,6 +337,8 @@
289 self.tarfile.add_file("1.0/empty.efi", b"")337 self.tarfile.add_file("1.0/empty.efi", b"")
290 self.tarfile.add_file("1.0/empty.ko", b"")338 self.tarfile.add_file("1.0/empty.ko", b"")
291 self.tarfile.add_file("1.0/empty.opal", b"")339 self.tarfile.add_file("1.0/empty.opal", b"")
340 self.tarfile.add_file("1.0/empty.sipl", b"")
341 self.tarfile.add_file("1.0/empty.fit", b"")
292 upload = self.process_emulate()342 upload = self.process_emulate()
293 expected_callers = [343 expected_callers = [
294 ('UEFI signing', 1),344 ('UEFI signing', 1),
@@ -304,6 +354,8 @@
304 self.tarfile.add_file("1.0/empty.efi", b"")354 self.tarfile.add_file("1.0/empty.efi", b"")
305 self.tarfile.add_file("1.0/empty.ko", b"")355 self.tarfile.add_file("1.0/empty.ko", b"")
306 self.tarfile.add_file("1.0/empty.opal", b"")356 self.tarfile.add_file("1.0/empty.opal", b"")
357 self.tarfile.add_file("1.0/empty.sipl", b"")
358 self.tarfile.add_file("1.0/empty.fit", b"")
307 upload = self.process_emulate()359 upload = self.process_emulate()
308 expected_callers = [360 expected_callers = [
309 ('UEFI keygen', 1),361 ('UEFI keygen', 1),
@@ -311,9 +363,14 @@
311 ('Kmod keygen cert', 1),363 ('Kmod keygen cert', 1),
312 ('Opal keygen key', 1),364 ('Opal keygen key', 1),
313 ('Opal keygen cert', 1),365 ('Opal keygen cert', 1),
366 ('Sipl keygen key', 1),
367 ('Sipl keygen cert', 1),
368 ('Fit keygen', 1),
314 ('UEFI signing', 1),369 ('UEFI signing', 1),
315 ('Kmod signing', 1),370 ('Kmod signing', 1),
316 ('Opal signing', 1),371 ('Opal signing', 1),
372 ('Sipl signing', 1),
373 ('Fit signing', 1),
317 ]374 ]
318 self.assertContentEqual(expected_callers, upload.callLog.caller_list())375 self.assertContentEqual(expected_callers, upload.callLog.caller_list())
319376
@@ -387,16 +444,22 @@
387 self.setUpUefiKeys()444 self.setUpUefiKeys()
388 self.setUpKmodKeys()445 self.setUpKmodKeys()
389 self.setUpOpalKeys()446 self.setUpOpalKeys()
447 self.setUpSiplKeys()
448 self.setUpFitKeys()
390 self.openArchive("test", "1.0", "amd64")449 self.openArchive("test", "1.0", "amd64")
391 self.tarfile.add_file("1.0/empty.efi", b"")450 self.tarfile.add_file("1.0/empty.efi", b"")
392 self.tarfile.add_file("1.0/empty.ko", b"")451 self.tarfile.add_file("1.0/empty.ko", b"")
393 self.tarfile.add_file("1.0/empty.opal", b"")452 self.tarfile.add_file("1.0/empty.opal", b"")
453 self.tarfile.add_file("1.0/empty.sipl", b"")
454 self.tarfile.add_file("1.0/empty.fit", b"")
394 self.process_emulate()455 self.process_emulate()
395 self.assertThat(self.getSignedPath("test", "amd64"), SignedMatches([456 self.assertThat(self.getSignedPath("test", "amd64"), SignedMatches([
396 "1.0/SHA256SUMS",457 "1.0/SHA256SUMS",
397 "1.0/empty.efi", "1.0/empty.efi.signed", "1.0/control/uefi.crt",458 "1.0/empty.efi", "1.0/empty.efi.signed", "1.0/control/uefi.crt",
398 "1.0/empty.ko", "1.0/empty.ko.sig", "1.0/control/kmod.x509",459 "1.0/empty.ko", "1.0/empty.ko.sig", "1.0/control/kmod.x509",
399 "1.0/empty.opal", "1.0/empty.opal.sig", "1.0/control/opal.x509",460 "1.0/empty.opal", "1.0/empty.opal.sig", "1.0/control/opal.x509",
461 "1.0/empty.sipl", "1.0/empty.sipl.sig", "1.0/control/sipl.x509",
462 "1.0/empty.fit", "1.0/empty.fit.signed", "1.0/control/fit.crt",
400 ]))463 ]))
401464
402 def test_options_tarball(self):465 def test_options_tarball(self):
@@ -405,11 +468,15 @@
405 self.setUpUefiKeys()468 self.setUpUefiKeys()
406 self.setUpKmodKeys()469 self.setUpKmodKeys()
407 self.setUpOpalKeys()470 self.setUpOpalKeys()
471 self.setUpSiplKeys()
472 self.setUpFitKeys()
408 self.openArchive("test", "1.0", "amd64")473 self.openArchive("test", "1.0", "amd64")
409 self.tarfile.add_file("1.0/control/options", b"tarball")474 self.tarfile.add_file("1.0/control/options", b"tarball")
410 self.tarfile.add_file("1.0/empty.efi", b"")475 self.tarfile.add_file("1.0/empty.efi", b"")
411 self.tarfile.add_file("1.0/empty.ko", b"")476 self.tarfile.add_file("1.0/empty.ko", b"")
412 self.tarfile.add_file("1.0/empty.opal", b"")477 self.tarfile.add_file("1.0/empty.opal", b"")
478 self.tarfile.add_file("1.0/empty.sipl", b"")
479 self.tarfile.add_file("1.0/empty.fit", b"")
413 self.process_emulate()480 self.process_emulate()
414 self.assertThat(self.getSignedPath("test", "amd64"), SignedMatches([481 self.assertThat(self.getSignedPath("test", "amd64"), SignedMatches([
415 "1.0/SHA256SUMS",482 "1.0/SHA256SUMS",
@@ -425,6 +492,10 @@
425 '1.0/empty.ko', '1.0/empty.ko.sig', '1.0/control/kmod.x509',492 '1.0/empty.ko', '1.0/empty.ko.sig', '1.0/control/kmod.x509',
426 '1.0/empty.opal', '1.0/empty.opal.sig',493 '1.0/empty.opal', '1.0/empty.opal.sig',
427 '1.0/control/opal.x509',494 '1.0/control/opal.x509',
495 '1.0/empty.sipl', '1.0/empty.sipl.sig',
496 '1.0/control/sipl.x509',
497 '1.0/empty.fit', '1.0/empty.fit.signed',
498 '1.0/control/fit.crt',
428 ], tarball.getnames())499 ], tarball.getnames())
429500
430 def test_options_signed_only(self):501 def test_options_signed_only(self):
@@ -433,17 +504,23 @@
433 self.setUpUefiKeys()504 self.setUpUefiKeys()
434 self.setUpKmodKeys()505 self.setUpKmodKeys()
435 self.setUpOpalKeys()506 self.setUpOpalKeys()
507 self.setUpSiplKeys()
508 self.setUpFitKeys()
436 self.openArchive("test", "1.0", "amd64")509 self.openArchive("test", "1.0", "amd64")
437 self.tarfile.add_file("1.0/control/options", b"signed-only")510 self.tarfile.add_file("1.0/control/options", b"signed-only")
438 self.tarfile.add_file("1.0/empty.efi", b"")511 self.tarfile.add_file("1.0/empty.efi", b"")
439 self.tarfile.add_file("1.0/empty.ko", b"")512 self.tarfile.add_file("1.0/empty.ko", b"")
440 self.tarfile.add_file("1.0/empty.opal", b"")513 self.tarfile.add_file("1.0/empty.opal", b"")
514 self.tarfile.add_file("1.0/empty.sipl", b"")
515 self.tarfile.add_file("1.0/empty.fit", b"")
441 self.process_emulate()516 self.process_emulate()
442 self.assertThat(self.getSignedPath("test", "amd64"), SignedMatches([517 self.assertThat(self.getSignedPath("test", "amd64"), SignedMatches([
443 "1.0/SHA256SUMS", "1.0/control/options",518 "1.0/SHA256SUMS", "1.0/control/options",
444 "1.0/empty.efi.signed", "1.0/control/uefi.crt",519 "1.0/empty.efi.signed", "1.0/control/uefi.crt",
445 "1.0/empty.ko.sig", "1.0/control/kmod.x509",520 "1.0/empty.ko.sig", "1.0/control/kmod.x509",
446 "1.0/empty.opal.sig", "1.0/control/opal.x509",521 "1.0/empty.opal.sig", "1.0/control/opal.x509",
522 "1.0/empty.sipl.sig", "1.0/control/sipl.x509",
523 "1.0/empty.fit.signed", "1.0/control/fit.crt",
447 ]))524 ]))
448525
449 def test_options_tarball_signed_only(self):526 def test_options_tarball_signed_only(self):
@@ -453,11 +530,15 @@
453 self.setUpUefiKeys()530 self.setUpUefiKeys()
454 self.setUpKmodKeys()531 self.setUpKmodKeys()
455 self.setUpOpalKeys()532 self.setUpOpalKeys()
533 self.setUpSiplKeys()
534 self.setUpFitKeys()
456 self.openArchive("test", "1.0", "amd64")535 self.openArchive("test", "1.0", "amd64")
457 self.tarfile.add_file("1.0/control/options", b"tarball\nsigned-only")536 self.tarfile.add_file("1.0/control/options", b"tarball\nsigned-only")
458 self.tarfile.add_file("1.0/empty.efi", b"")537 self.tarfile.add_file("1.0/empty.efi", b"")
459 self.tarfile.add_file("1.0/empty.ko", b"")538 self.tarfile.add_file("1.0/empty.ko", b"")
460 self.tarfile.add_file("1.0/empty.opal", b"")539 self.tarfile.add_file("1.0/empty.opal", b"")
540 self.tarfile.add_file("1.0/empty.sipl", b"")
541 self.tarfile.add_file("1.0/empty.fit", b"")
461 self.process_emulate()542 self.process_emulate()
462 self.assertThat(self.getSignedPath("test", "amd64"), SignedMatches([543 self.assertThat(self.getSignedPath("test", "amd64"), SignedMatches([
463 "1.0/SHA256SUMS",544 "1.0/SHA256SUMS",
@@ -471,12 +552,18 @@
471 '1.0/empty.efi.signed', '1.0/control/uefi.crt',552 '1.0/empty.efi.signed', '1.0/control/uefi.crt',
472 '1.0/empty.ko.sig', '1.0/control/kmod.x509',553 '1.0/empty.ko.sig', '1.0/control/kmod.x509',
473 '1.0/empty.opal.sig', '1.0/control/opal.x509',554 '1.0/empty.opal.sig', '1.0/control/opal.x509',
555 '1.0/empty.sipl.sig', '1.0/control/sipl.x509',
556 '1.0/empty.fit.signed', '1.0/control/fit.crt',
474 ], tarball.getnames())557 ], tarball.getnames())
475558
476 def test_no_signed_files(self):559 def test_no_signed_files(self):
477 # Tarballs containing no *.efi files are extracted without complaint.560 # Tarballs containing no *.efi files are extracted without complaint.
478 # Nothing is signed.561 # Nothing is signed.
479 self.setUpUefiKeys()562 self.setUpUefiKeys()
563 self.setUpKmodKeys()
564 self.setUpOpalKeys()
565 self.setUpSiplKeys()
566 self.setUpFitKeys()
480 self.openArchive("empty", "1.0", "amd64")567 self.openArchive("empty", "1.0", "amd64")
481 self.tarfile.add_file("1.0/hello", b"world")568 self.tarfile.add_file("1.0/hello", b"world")
482 upload = self.process()569 upload = self.process()
@@ -484,6 +571,9 @@
484 self.getSignedPath("empty", "amd64"), "1.0", "hello")))571 self.getSignedPath("empty", "amd64"), "1.0", "hello")))
485 self.assertEqual(0, upload.signUefi.call_count)572 self.assertEqual(0, upload.signUefi.call_count)
486 self.assertEqual(0, upload.signKmod.call_count)573 self.assertEqual(0, upload.signKmod.call_count)
574 self.assertEqual(0, upload.signOpal.call_count)
575 self.assertEqual(0, upload.signSipl.call_count)
576 self.assertEqual(0, upload.signFit.call_count)
487577
488 def test_already_exists(self):578 def test_already_exists(self):
489 # If the target directory already exists, processing fails.579 # If the target directory already exists, processing fails.
@@ -551,7 +641,71 @@
551 args = fake_call.calls[0][0][0]641 args = fake_call.calls[0][0][0]
552 expected_cmd = [642 expected_cmd = [
553 'openssl', 'req', '-new', '-x509', '-newkey', 'rsa:2048',643 'openssl', 'req', '-new', '-x509', '-newkey', 'rsa:2048',
554 '-subj', self.testcase_cn, '-keyout', self.key, '-out', self.cert,644 '-subj', '/CN=' + self.testcase_cn + ' UEFI/',
645 '-keyout', self.key, '-out', self.cert,
646 '-days', '3650', '-nodes', '-sha256',
647 ]
648 self.assertEqual(expected_cmd, args)
649
650 def test_correct_fit_signing_command_executed(self):
651 # Check that calling signFit() will generate the expected command
652 # when appropriate keys are present.
653 self.setUpFitKeys()
654 fake_call = FakeMethod(result=0)
655 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
656 fake_copy = FakeMethod(result=0)
657 self.useFixture(MonkeyPatch("shutil.copy", fake_copy))
658 upload = SigningUpload()
659 upload.generateFitKeys = FakeMethod()
660 upload.setTargetDirectory(
661 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
662 upload.signFit('t.fit')
663 # Confirm the copy was performed.
664 self.assertEqual(1, fake_copy.call_count)
665 args = fake_copy.calls[0][0]
666 expected_copy = ('t.fit', 't.fit.signed')
667 self.assertEqual(expected_copy, args)
668 # Assert command form.
669 args = fake_call.calls[0][0][0]
670 expected_cmd = [
671 'mkimage', '-F', '-k', os.path.dirname(self.fit_key), '-r',
672 't.fit.signed',
673 ]
674 self.assertEqual(expected_cmd, args)
675 self.assertEqual(0, upload.generateFitKeys.call_count)
676
677 def test_correct_fit_signing_command_executed_no_keys(self):
678 # Check that calling signFit() will generate no commands when
679 # no keys are present.
680 self.setUpFitKeys(create=False)
681 fake_call = FakeMethod(result=0)
682 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
683 upload = SigningUpload()
684 upload.generateFitKeys = FakeMethod()
685 upload.setTargetDirectory(
686 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
687 upload.signUefi('t.fit')
688 self.assertEqual(0, fake_call.call_count)
689 self.assertEqual(0, upload.generateFitKeys.call_count)
690
691 def test_correct_fit_keygen_command_executed(self):
692 # Check that calling generateFitKeys() will generate the
693 # expected command.
694 self.setUpPPA()
695 self.setUpFitKeys(create=False)
696 fake_call = FakeMethod(result=0)
697 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
698 upload = SigningUpload()
699 upload.setTargetDirectory(
700 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
701 upload.generateFitKeys()
702 self.assertEqual(1, fake_call.call_count)
703 # Assert the actual command matches.
704 args = fake_call.calls[0][0][0]
705 expected_cmd = [
706 'openssl', 'req', '-new', '-x509', '-newkey', 'rsa:2048',
707 '-subj', '/CN=' + self.testcase_cn + ' Fit/',
708 '-keyout', self.fit_key, '-out', self.fit_cert,
555 '-days', '3650', '-nodes', '-sha256',709 '-days', '3650', '-nodes', '-sha256',
556 ]710 ]
557 self.assertEqual(expected_cmd, args)711 self.assertEqual(expected_cmd, args)
@@ -559,15 +713,20 @@
559 def test_correct_kmod_openssl_config(self):713 def test_correct_kmod_openssl_config(self):
560 # Check that calling generateOpensslConfig() will return an appropriate714 # Check that calling generateOpensslConfig() will return an appropriate
561 # openssl configuration.715 # openssl configuration.
716 self.setUpPPA()
562 upload = SigningUpload()717 upload = SigningUpload()
563 text = upload.generateOpensslConfig('Kmod', 'something-unique')718 upload.setTargetDirectory(
719 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
720 text = upload.generateOpensslConfig('Kmod', upload.openssl_config_kmod)
564721
565 cn_re = re.compile(r'\bCN\s*=\s*something-unique\b')722 id_re = re.compile(r'^# KMOD openssl config\b')
723 cn_re = re.compile(r'\bCN\s*=\s*' + self.testcase_cn + '\s+Kmod')
566 eku_re = re.compile(724 eku_re = re.compile(
567 r'\bextendedKeyUsage\s*=\s*'725 r'\bextendedKeyUsage\s*=\s*'
568 r'codeSigning,1.3.6.1.4.1.2312.16.1.2\s*\b')726 r'codeSigning,1.3.6.1.4.1.2312.16.1.2\s*\b')
569727
570 self.assertIn('[ req ]', text)728 self.assertIn('[ req ]', text)
729 self.assertIsNotNone(id_re.search(text))
571 self.assertIsNotNone(cn_re.search(text))730 self.assertIsNotNone(cn_re.search(text))
572 self.assertIsNotNone(eku_re.search(text))731 self.assertIsNotNone(eku_re.search(text))
573732
@@ -640,12 +799,17 @@
640 def test_correct_opal_openssl_config(self):799 def test_correct_opal_openssl_config(self):
641 # Check that calling generateOpensslConfig() will return an appropriate800 # Check that calling generateOpensslConfig() will return an appropriate
642 # openssl configuration.801 # openssl configuration.
802 self.setUpPPA()
643 upload = SigningUpload()803 upload = SigningUpload()
644 text = upload.generateOpensslConfig('Opal', 'something-unique')804 upload.setTargetDirectory(
805 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
806 text = upload.generateOpensslConfig('Opal', upload.openssl_config_opal)
645807
646 cn_re = re.compile(r'\bCN\s*=\s*something-unique\b')808 id_re = re.compile(r'^# OPAL openssl config\b')
809 cn_re = re.compile(r'\bCN\s*=\s*' + self.testcase_cn + '\s+Opal')
647810
648 self.assertIn('[ req ]', text)811 self.assertIn('[ req ]', text)
812 self.assertIsNotNone(id_re.search(text))
649 self.assertIsNotNone(cn_re.search(text))813 self.assertIsNotNone(cn_re.search(text))
650 self.assertNotIn('extendedKeyUsage', text)814 self.assertNotIn('extendedKeyUsage', text)
651815
@@ -715,6 +879,89 @@
715 ]879 ]
716 self.assertEqual(expected_cmd, args)880 self.assertEqual(expected_cmd, args)
717881
882 def test_correct_sipl_openssl_config(self):
883 # Check that calling generateOpensslConfig() will return an appropriate
884 # openssl configuration.
885 self.setUpPPA()
886 upload = SigningUpload()
887 upload.setTargetDirectory(
888 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
889 text = upload.generateOpensslConfig('Sipl', upload.openssl_config_sipl)
890
891 id_re = re.compile(r'^# SIPL openssl config\b')
892 cn_re = re.compile(r'\bCN\s*=\s*' + self.testcase_cn + '\s+Sipl')
893
894 self.assertIn('[ req ]', text)
895 self.assertIsNotNone(id_re.search(text))
896 self.assertIsNotNone(cn_re.search(text))
897 self.assertNotIn('extendedKeyUsage', text)
898
899 def test_correct_sipl_signing_command_executed(self):
900 # Check that calling signSipl() will generate the expected command
901 # when appropriate keys are present.
902 self.setUpSiplKeys()
903 fake_call = FakeMethod(result=0)
904 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
905 upload = SigningUpload()
906 upload.generateSiplKeys = FakeMethod()
907 upload.setTargetDirectory(
908 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
909 upload.signSipl('t.sipl')
910 self.assertEqual(1, fake_call.call_count)
911 # Assert command form.
912 args = fake_call.calls[0][0][0]
913 expected_cmd = [
914 'kmodsign', '-D', 'sha512', self.sipl_pem, self.sipl_x509,
915 't.sipl', 't.sipl.sig'
916 ]
917 self.assertEqual(expected_cmd, args)
918 self.assertEqual(0, upload.generateSiplKeys.call_count)
919
920 def test_correct_sipl_signing_command_executed_no_keys(self):
921 # Check that calling signSipl() will generate no commands when
922 # no keys are present.
923 self.setUpSiplKeys(create=False)
924 fake_call = FakeMethod(result=0)
925 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
926 upload = SigningUpload()
927 upload.generateSiplKeys = FakeMethod()
928 upload.setTargetDirectory(
929 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
930 upload.signOpal('t.sipl')
931 self.assertEqual(0, fake_call.call_count)
932 self.assertEqual(0, upload.generateSiplKeys.call_count)
933
934 def test_correct_sipl_keygen_command_executed(self):
935 # Check that calling generateSiplKeys() will generate the
936 # expected command.
937 self.setUpPPA()
938 self.setUpSiplKeys(create=False)
939 fake_call = FakeMethod(result=0)
940 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
941 upload = SigningUpload()
942 upload.setTargetDirectory(
943 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
944 upload.generateSiplKeys()
945 self.assertEqual(2, fake_call.call_count)
946 # Assert the actual command matches.
947 args = fake_call.calls[0][0][0]
948 # Sanitise the keygen tmp file.
949 if args[11].endswith('.keygen'):
950 args[11] = 'XXX.keygen'
951 expected_cmd = [
952 'openssl', 'req', '-new', '-nodes', '-utf8', '-sha512',
953 '-days', '3650', '-batch', '-x509',
954 '-config', 'XXX.keygen', '-outform', 'PEM',
955 '-out', self.sipl_pem, '-keyout', self.sipl_pem
956 ]
957 self.assertEqual(expected_cmd, args)
958 args = fake_call.calls[1][0][0]
959 expected_cmd = [
960 'openssl', 'x509', '-in', self.sipl_pem, '-outform', 'DER',
961 '-out', self.sipl_x509
962 ]
963 self.assertEqual(expected_cmd, args)
964
718 def test_signs_uefi_image(self):965 def test_signs_uefi_image(self):
719 # Each image in the tarball is signed.966 # Each image in the tarball is signed.
720 self.setUpUefiKeys()967 self.setUpUefiKeys()
@@ -723,6 +970,14 @@
723 upload = self.process()970 upload = self.process()
724 self.assertEqual(1, upload.signUefi.call_count)971 self.assertEqual(1, upload.signUefi.call_count)
725972
973 def test_signs_fit_image(self):
974 # Each image in the tarball is signed.
975 self.setUpFitKeys()
976 self.openArchive("test", "1.0", "amd64")
977 self.tarfile.add_file("1.0/empty.fit", b"")
978 upload = self.process()
979 self.assertEqual(1, upload.signFit.call_count)
980
726 def test_signs_kmod_image(self):981 def test_signs_kmod_image(self):
727 # Each image in the tarball is signed.982 # Each image in the tarball is signed.
728 self.setUpKmodKeys()983 self.setUpKmodKeys()
@@ -739,9 +994,16 @@
739 upload = self.process()994 upload = self.process()
740 self.assertEqual(1, upload.signOpal.call_count)995 self.assertEqual(1, upload.signOpal.call_count)
741996
997 def test_signs_sipl_image(self):
998 # Each image in the tarball is signed.
999 self.setUpSiplKeys()
1000 self.openArchive("test", "1.0", "amd64")
1001 self.tarfile.add_file("1.0/empty.sipl", b"")
1002 upload = self.process()
1003 self.assertEqual(1, upload.signSipl.call_count)
1004
742 def test_signs_combo_image(self):1005 def test_signs_combo_image(self):
743 # Each image in the tarball is signed.1006 # Each image in the tarball is signed.
744 self.setUpKmodKeys()
745 self.openArchive("test", "1.0", "amd64")1007 self.openArchive("test", "1.0", "amd64")
746 self.tarfile.add_file("1.0/empty.efi", b"")1008 self.tarfile.add_file("1.0/empty.efi", b"")
747 self.tarfile.add_file("1.0/empty.ko", b"")1009 self.tarfile.add_file("1.0/empty.ko", b"")
@@ -749,10 +1011,21 @@
749 self.tarfile.add_file("1.0/empty.opal", b"")1011 self.tarfile.add_file("1.0/empty.opal", b"")
750 self.tarfile.add_file("1.0/empty2.opal", b"")1012 self.tarfile.add_file("1.0/empty2.opal", b"")
751 self.tarfile.add_file("1.0/empty3.opal", b"")1013 self.tarfile.add_file("1.0/empty3.opal", b"")
1014 self.tarfile.add_file("1.0/empty.sipl", b"")
1015 self.tarfile.add_file("1.0/empty2.sipl", b"")
1016 self.tarfile.add_file("1.0/empty3.sipl", b"")
1017 self.tarfile.add_file("1.0/empty4.sipl", b"")
1018 self.tarfile.add_file("1.0/empty.fit", b"")
1019 self.tarfile.add_file("1.0/empty2.fit", b"")
1020 self.tarfile.add_file("1.0/empty3.fit", b"")
1021 self.tarfile.add_file("1.0/empty4.fit", b"")
1022 self.tarfile.add_file("1.0/empty5.fit", b"")
752 upload = self.process()1023 upload = self.process()
753 self.assertEqual(1, upload.signUefi.call_count)1024 self.assertEqual(1, upload.signUefi.call_count)
754 self.assertEqual(2, upload.signKmod.call_count)1025 self.assertEqual(2, upload.signKmod.call_count)
755 self.assertEqual(3, upload.signOpal.call_count)1026 self.assertEqual(3, upload.signOpal.call_count)
1027 self.assertEqual(4, upload.signSipl.call_count)
1028 self.assertEqual(5, upload.signFit.call_count)
7561029
757 def test_installed(self):1030 def test_installed(self):
758 # Files in the tarball are installed correctly.1031 # Files in the tarball are installed correctly.
@@ -824,6 +1097,43 @@
824 self.assertEqual(stat.S_IMODE(os.stat(self.key).st_mode), 0o600)1097 self.assertEqual(stat.S_IMODE(os.stat(self.key).st_mode), 0o600)
825 self.assertEqual(stat.S_IMODE(os.stat(self.cert).st_mode), 0o644)1098 self.assertEqual(stat.S_IMODE(os.stat(self.cert).st_mode), 0o644)
8261099
1100 def test_create_fit_keys_autokey_off(self):
1101 # Keys are not created.
1102 self.setUpFitKeys(create=False)
1103 self.assertFalse(os.path.exists(self.fit_key))
1104 self.assertFalse(os.path.exists(self.fit_cert))
1105 fake_call = FakeMethod(result=0)
1106 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
1107 upload = SigningUpload()
1108 upload.callLog = FakeMethodCallLog(upload=upload)
1109 upload.setTargetDirectory(
1110 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
1111 upload.signFit(os.path.join(self.makeTemporaryDirectory(), 'fit'))
1112 self.assertEqual(0, upload.callLog.caller_count('Fit keygen'))
1113 self.assertFalse(os.path.exists(self.fit_key))
1114 self.assertFalse(os.path.exists(self.fit_cert))
1115
1116 def test_create_fit_keys_autokey_on(self):
1117 # Keys are created on demand.
1118 self.setUpPPA()
1119 self.setUpFitKeys(create=False)
1120 self.assertFalse(os.path.exists(self.fit_key))
1121 self.assertFalse(os.path.exists(self.fit_cert))
1122 fake_call = FakeMethod(result=0)
1123 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
1124 fake_copy = FakeMethod(result=0)
1125 self.useFixture(MonkeyPatch("shutil.copy", fake_copy))
1126 upload = SigningUpload()
1127 upload.callLog = FakeMethodCallLog(upload=upload)
1128 upload.setTargetDirectory(
1129 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
1130 upload.signFit(os.path.join(self.makeTemporaryDirectory(), 't.fit'))
1131 self.assertEqual(1, upload.callLog.caller_count('Fit keygen'))
1132 self.assertTrue(os.path.exists(self.fit_key))
1133 self.assertTrue(os.path.exists(self.fit_cert))
1134 self.assertEqual(stat.S_IMODE(os.stat(self.fit_key).st_mode), 0o600)
1135 self.assertEqual(stat.S_IMODE(os.stat(self.fit_cert).st_mode), 0o644)
1136
827 def test_create_kmod_keys_autokey_off(self):1137 def test_create_kmod_keys_autokey_off(self):
828 # Keys are not created.1138 # Keys are not created.
829 self.setUpKmodKeys(create=False)1139 self.setUpKmodKeys(create=False)
@@ -898,16 +1208,55 @@
898 self.assertEqual(stat.S_IMODE(os.stat(self.opal_pem).st_mode), 0o600)1208 self.assertEqual(stat.S_IMODE(os.stat(self.opal_pem).st_mode), 0o600)
899 self.assertEqual(stat.S_IMODE(os.stat(self.opal_x509).st_mode), 0o644)1209 self.assertEqual(stat.S_IMODE(os.stat(self.opal_x509).st_mode), 0o644)
9001210
1211 def test_create_sipl_keys_autokey_off(self):
1212 # Keys are not created.
1213 self.setUpSiplKeys(create=False)
1214 self.assertFalse(os.path.exists(self.sipl_pem))
1215 self.assertFalse(os.path.exists(self.sipl_x509))
1216 fake_call = FakeMethod(result=0)
1217 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
1218 upload = SigningUpload()
1219 upload.callLog = FakeMethodCallLog(upload=upload)
1220 upload.setTargetDirectory(
1221 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
1222 upload.signOpal(os.path.join(self.makeTemporaryDirectory(), 't.sipl'))
1223 self.assertEqual(0, upload.callLog.caller_count('Sipl keygen key'))
1224 self.assertEqual(0, upload.callLog.caller_count('Sipl keygen cert'))
1225 self.assertFalse(os.path.exists(self.sipl_pem))
1226 self.assertFalse(os.path.exists(self.sipl_x509))
1227
1228 def test_create_sipl_keys_autokey_on(self):
1229 # Keys are created on demand.
1230 self.setUpPPA()
1231 self.setUpSiplKeys(create=False)
1232 self.assertFalse(os.path.exists(self.sipl_pem))
1233 self.assertFalse(os.path.exists(self.sipl_x509))
1234 fake_call = FakeMethod(result=0)
1235 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
1236 upload = SigningUpload()
1237 upload.callLog = FakeMethodCallLog(upload=upload)
1238 upload.setTargetDirectory(
1239 self.archive, "test_1.0_amd64.tar.gz", "distroseries")
1240 upload.signSipl(os.path.join(self.makeTemporaryDirectory(), 't.sipl'))
1241 self.assertEqual(1, upload.callLog.caller_count('Sipl keygen key'))
1242 self.assertEqual(1, upload.callLog.caller_count('Sipl keygen cert'))
1243 self.assertTrue(os.path.exists(self.sipl_pem))
1244 self.assertTrue(os.path.exists(self.sipl_x509))
1245 self.assertEqual(stat.S_IMODE(os.stat(self.sipl_pem).st_mode), 0o600)
1246 self.assertEqual(stat.S_IMODE(os.stat(self.sipl_x509).st_mode), 0o644)
1247
901 def test_checksumming_tree(self):1248 def test_checksumming_tree(self):
902 # Specifying no options should leave us with an open tree,1249 # Specifying no options should leave us with an open tree,
903 # confirm it is checksummed.1250 # confirm it is checksummed.
904 self.setUpUefiKeys()1251 self.setUpUefiKeys()
905 self.setUpKmodKeys()1252 self.setUpKmodKeys()
906 self.setUpOpalKeys()1253 self.setUpOpalKeys()
1254 self.setUpSiplKeys()
907 self.openArchive("test", "1.0", "amd64")1255 self.openArchive("test", "1.0", "amd64")
908 self.tarfile.add_file("1.0/empty.efi", b"")1256 self.tarfile.add_file("1.0/empty.efi", b"")
909 self.tarfile.add_file("1.0/empty.ko", b"")1257 self.tarfile.add_file("1.0/empty.ko", b"")
910 self.tarfile.add_file("1.0/empty.opal", b"")1258 self.tarfile.add_file("1.0/empty.opal", b"")
1259 self.tarfile.add_file("1.0/empty.sipl", b"")
911 self.process_emulate()1260 self.process_emulate()
912 sha256file = os.path.join(self.getSignedPath("test", "amd64"),1261 sha256file = os.path.join(self.getSignedPath("test", "amd64"),
913 "1.0", "SHA256SUMS")1262 "1.0", "SHA256SUMS")
@@ -926,6 +1275,7 @@
926 self.tarfile.add_file("1.0/empty.efi", b"")1275 self.tarfile.add_file("1.0/empty.efi", b"")
927 self.tarfile.add_file("1.0/empty.ko", b"")1276 self.tarfile.add_file("1.0/empty.ko", b"")
928 self.tarfile.add_file("1.0/empty.opal", b"")1277 self.tarfile.add_file("1.0/empty.opal", b"")
1278 self.tarfile.add_file("1.0/empty.sipl", b"")
929 self.process_emulate()1279 self.process_emulate()
930 sha256file = os.path.join(self.getSignedPath("test", "amd64"),1280 sha256file = os.path.join(self.getSignedPath("test", "amd64"),
931 "1.0", "SHA256SUMS")1281 "1.0", "SHA256SUMS")
@@ -949,6 +1299,7 @@
949 self.tarfile.add_file("1.0/empty.efi", b"")1299 self.tarfile.add_file("1.0/empty.efi", b"")
950 self.tarfile.add_file("1.0/empty.ko", b"")1300 self.tarfile.add_file("1.0/empty.ko", b"")
951 self.tarfile.add_file("1.0/empty.opal", b"")1301 self.tarfile.add_file("1.0/empty.opal", b"")
1302 self.tarfile.add_file("1.0/empty.sipl", b"")
952 self.process_emulate()1303 self.process_emulate()
953 sha256file = os.path.join(self.getSignedPath("test", "amd64"),1304 sha256file = os.path.join(self.getSignedPath("test", "amd64"),
954 "1.0", "SHA256SUMS")1305 "1.0", "SHA256SUMS")
@@ -982,6 +1333,7 @@
982 self.tarfile.add_file("1.0/empty.efi", "")1333 self.tarfile.add_file("1.0/empty.efi", "")
983 self.tarfile.add_file("1.0/empty.ko", "")1334 self.tarfile.add_file("1.0/empty.ko", "")
984 self.tarfile.add_file("1.0/empty.opal", "")1335 self.tarfile.add_file("1.0/empty.opal", "")
1336 self.tarfile.add_file("1.0/empty.sipl", "")
985 self.process_emulate()1337 self.process_emulate()
986 sha256file = os.path.join(self.getSignedPath("test", "amd64"),1338 sha256file = os.path.join(self.getSignedPath("test", "amd64"),
987 "1.0", "SHA256SUMS")1339 "1.0", "SHA256SUMS")