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
1=== modified file 'lib/lp/archivepublisher/signing.py'
2--- lib/lp/archivepublisher/signing.py 2018-05-06 08:52:34 +0000
3+++ lib/lp/archivepublisher/signing.py 2018-08-03 16:18:11 +0000
4@@ -242,6 +242,41 @@
5 cmdl = ["sbsign", "--key", key, "--cert", cert, image]
6 return self.callLog("UEFI signing", cmdl)
7
8+ openssl_config_opal = textwrap.dedent("""
9+ [ req ]
10+ default_bits = 4096
11+ distinguished_name = req_distinguished_name
12+ prompt = no
13+ string_mask = utf8only
14+ x509_extensions = myexts
15+
16+ [ req_distinguished_name ]
17+ CN = {common_name}
18+
19+ [ myexts ]
20+ basicConstraints=critical,CA:FALSE
21+ keyUsage=digitalSignature
22+ subjectKeyIdentifier=hash
23+ authorityKeyIdentifier=keyid
24+ """)
25+
26+ openssl_config_kmod = openssl_config_opal + textwrap.dedent("""
27+ # codeSigning: specifies that this key is used to sign code.
28+ # 1.3.6.1.4.1.2312.16.1.2: defines this key as used for
29+ # module signing only. See https://lkml.org/lkml/2015/8/26/741.
30+ extendedKeyUsage = codeSigning,1.3.6.1.4.1.2312.16.1.2
31+ """)
32+
33+ def generateOpensslConfig(self, key_type, common_name):
34+ if key_type == 'Kmod':
35+ genkey_tmpl = self.openssl_config_kmod
36+ elif key_type == 'Opal':
37+ genkey_tmpl = self.openssl_config_opal
38+ else:
39+ raise ValueError("unknown key_type " + key_type)
40+
41+ return genkey_tmpl.format(common_name=common_name)
42+
43 def generatePemX509Pair(self, key_type, pem_filename, x509_filename):
44 """Generate new pem/x509 key pairs."""
45 directory = os.path.dirname(pem_filename)
46@@ -255,24 +290,7 @@
47 old_mask = os.umask(0o077)
48 try:
49 with tempfile.NamedTemporaryFile(suffix='.keygen') as tf:
50- genkey_text = textwrap.dedent("""\
51- [ req ]
52- default_bits = 4096
53- distinguished_name = req_distinguished_name
54- prompt = no
55- string_mask = utf8only
56- x509_extensions = myexts
57-
58- [ req_distinguished_name ]
59- CN = %s
60-
61- [ myexts ]
62- basicConstraints=critical,CA:FALSE
63- keyUsage=digitalSignature
64- subjectKeyIdentifier=hash
65- authorityKeyIdentifier=keyid
66- """ % common_name)
67-
68+ genkey_text = self.generateOpensslConfig(key_type, common_name)
69 print(genkey_text, file=tf)
70
71 # Close out the underlying file so we know it is complete.
72
73=== modified file 'lib/lp/archivepublisher/tests/test_signing.py'
74--- lib/lp/archivepublisher/tests/test_signing.py 2018-05-06 08:52:34 +0000
75+++ lib/lp/archivepublisher/tests/test_signing.py 2018-08-03 16:18:11 +0000
76@@ -8,6 +8,7 @@
77 __metaclass__ = type
78
79 import os
80+import re
81 import stat
82 import tarfile
83
84@@ -555,6 +556,21 @@
85 ]
86 self.assertEqual(expected_cmd, args)
87
88+ def test_correct_kmod_openssl_config(self):
89+ # Check that calling generateOpensslConfig() will return an appropriate
90+ # openssl configuration.
91+ upload = SigningUpload()
92+ text = upload.generateOpensslConfig('Kmod', 'something-unique')
93+
94+ cn_re = re.compile(r'\bCN\s*=\s*something-unique\b')
95+ eku_re = re.compile(
96+ r'\bextendedKeyUsage\s*=\s*'
97+ r'codeSigning,1.3.6.1.4.1.2312.16.1.2\s*\b')
98+
99+ self.assertIn('[ req ]', text)
100+ self.assertIsNotNone(cn_re.search(text))
101+ self.assertIsNotNone(eku_re.search(text))
102+
103 def test_correct_kmod_signing_command_executed(self):
104 # Check that calling signKmod() will generate the expected command
105 # when appropriate keys are present.
106@@ -621,6 +637,18 @@
107 ]
108 self.assertEqual(expected_cmd, args)
109
110+ def test_correct_opal_openssl_config(self):
111+ # Check that calling generateOpensslConfig() will return an appropriate
112+ # openssl configuration.
113+ upload = SigningUpload()
114+ text = upload.generateOpensslConfig('Opal', 'something-unique')
115+
116+ cn_re = re.compile(r'\bCN\s*=\s*something-unique\b')
117+
118+ self.assertIn('[ req ]', text)
119+ self.assertIsNotNone(cn_re.search(text))
120+ self.assertNotIn('extendedKeyUsage', text)
121+
122 def test_correct_opal_signing_command_executed(self):
123 # Check that calling signOpal() will generate the expected command
124 # when appropriate keys are present.