Merge lp:~apw/launchpad/signing-kmod-extended-key-usage into lp:launchpad

Proposed by Andy Whitcroft
Status: Merged
Merged at revision: 18744
Proposed branch: lp:~apw/launchpad/signing-kmod-extended-key-usage
Merge into: lp:launchpad
Diff against target: 124 lines (+64/-18)
2 files modified
lib/lp/archivepublisher/signing.py (+36/-18)
lib/lp/archivepublisher/tests/test_signing.py (+28/-0)
To merge this branch: bzr merge lp:~apw/launchpad/signing-kmod-extended-key-usage
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+352305@code.launchpad.net

Commit message

Add kmod extendedKeyUsage information to restrict the keys to signing of modules only. This prevents those keys being used as EFI kernel signing keys.

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
review: Approve
Revision history for this message
Andy Whitcroft (apw) wrote :

All sensible. Applied and pushed.

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-05-06 08:52:34 +0000
+++ lib/lp/archivepublisher/signing.py 2018-08-03 16:18:11 +0000
@@ -242,6 +242,41 @@
242 cmdl = ["sbsign", "--key", key, "--cert", cert, image]242 cmdl = ["sbsign", "--key", key, "--cert", cert, image]
243 return self.callLog("UEFI signing", cmdl)243 return self.callLog("UEFI signing", cmdl)
244244
245 openssl_config_opal = textwrap.dedent("""
246 [ req ]
247 default_bits = 4096
248 distinguished_name = req_distinguished_name
249 prompt = no
250 string_mask = utf8only
251 x509_extensions = myexts
252
253 [ req_distinguished_name ]
254 CN = {common_name}
255
256 [ myexts ]
257 basicConstraints=critical,CA:FALSE
258 keyUsage=digitalSignature
259 subjectKeyIdentifier=hash
260 authorityKeyIdentifier=keyid
261 """)
262
263 openssl_config_kmod = openssl_config_opal + textwrap.dedent("""
264 # 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 for
266 # module signing only. See https://lkml.org/lkml/2015/8/26/741.
267 extendedKeyUsage = codeSigning,1.3.6.1.4.1.2312.16.1.2
268 """)
269
270 def generateOpensslConfig(self, key_type, common_name):
271 if key_type == 'Kmod':
272 genkey_tmpl = self.openssl_config_kmod
273 elif key_type == 'Opal':
274 genkey_tmpl = self.openssl_config_opal
275 else:
276 raise ValueError("unknown key_type " + key_type)
277
278 return genkey_tmpl.format(common_name=common_name)
279
245 def generatePemX509Pair(self, key_type, pem_filename, x509_filename):280 def generatePemX509Pair(self, key_type, pem_filename, x509_filename):
246 """Generate new pem/x509 key pairs."""281 """Generate new pem/x509 key pairs."""
247 directory = os.path.dirname(pem_filename)282 directory = os.path.dirname(pem_filename)
@@ -255,24 +290,7 @@
255 old_mask = os.umask(0o077)290 old_mask = os.umask(0o077)
256 try:291 try:
257 with tempfile.NamedTemporaryFile(suffix='.keygen') as tf:292 with tempfile.NamedTemporaryFile(suffix='.keygen') as tf:
258 genkey_text = textwrap.dedent("""\293 genkey_text = self.generateOpensslConfig(key_type, common_name)
259 [ req ]
260 default_bits = 4096
261 distinguished_name = req_distinguished_name
262 prompt = no
263 string_mask = utf8only
264 x509_extensions = myexts
265
266 [ req_distinguished_name ]
267 CN = %s
268
269 [ myexts ]
270 basicConstraints=critical,CA:FALSE
271 keyUsage=digitalSignature
272 subjectKeyIdentifier=hash
273 authorityKeyIdentifier=keyid
274 """ % common_name)
275
276 print(genkey_text, file=tf)294 print(genkey_text, file=tf)
277295
278 # Close out the underlying file so we know it is complete.296 # Close out the underlying file so we know it is complete.
279297
=== modified file 'lib/lp/archivepublisher/tests/test_signing.py'
--- lib/lp/archivepublisher/tests/test_signing.py 2018-05-06 08:52:34 +0000
+++ lib/lp/archivepublisher/tests/test_signing.py 2018-08-03 16:18:11 +0000
@@ -8,6 +8,7 @@
8__metaclass__ = type8__metaclass__ = type
99
10import os10import os
11import re
11import stat12import stat
12import tarfile13import tarfile
1314
@@ -555,6 +556,21 @@
555 ]556 ]
556 self.assertEqual(expected_cmd, args)557 self.assertEqual(expected_cmd, args)
557558
559 def test_correct_kmod_openssl_config(self):
560 # Check that calling generateOpensslConfig() will return an appropriate
561 # openssl configuration.
562 upload = SigningUpload()
563 text = upload.generateOpensslConfig('Kmod', 'something-unique')
564
565 cn_re = re.compile(r'\bCN\s*=\s*something-unique\b')
566 eku_re = re.compile(
567 r'\bextendedKeyUsage\s*=\s*'
568 r'codeSigning,1.3.6.1.4.1.2312.16.1.2\s*\b')
569
570 self.assertIn('[ req ]', text)
571 self.assertIsNotNone(cn_re.search(text))
572 self.assertIsNotNone(eku_re.search(text))
573
558 def test_correct_kmod_signing_command_executed(self):574 def test_correct_kmod_signing_command_executed(self):
559 # Check that calling signKmod() will generate the expected command575 # Check that calling signKmod() will generate the expected command
560 # when appropriate keys are present.576 # when appropriate keys are present.
@@ -621,6 +637,18 @@
621 ]637 ]
622 self.assertEqual(expected_cmd, args)638 self.assertEqual(expected_cmd, args)
623639
640 def test_correct_opal_openssl_config(self):
641 # Check that calling generateOpensslConfig() will return an appropriate
642 # openssl configuration.
643 upload = SigningUpload()
644 text = upload.generateOpensslConfig('Opal', 'something-unique')
645
646 cn_re = re.compile(r'\bCN\s*=\s*something-unique\b')
647
648 self.assertIn('[ req ]', text)
649 self.assertIsNotNone(cn_re.search(text))
650 self.assertNotIn('extendedKeyUsage', text)
651
624 def test_correct_opal_signing_command_executed(self):652 def test_correct_opal_signing_command_executed(self):
625 # Check that calling signOpal() will generate the expected command653 # Check that calling signOpal() will generate the expected command
626 # when appropriate keys are present.654 # when appropriate keys are present.