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

Proposed by Andy Whitcroft on 2018-08-03
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 2018-08-03 Approve on 2018-08-03
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.
18744. By Andy Whitcroft on 2018-08-03

signing: add extendedKeyUsage = codeSigning,1.3.6.1.4.1.2312.16.1.2 to kmod keys

In order to prevent kernel module signing keys from also
being usable to sign kernels add the extendedKeyUsage of
codeSigning,1.3.6.1.4.1.2312.16.1.2 to the OpenSSL configuration
when generating these keys.

Take this opportunity to pull out the OpenSSL configuration
generation so that it can be validated during testing.

Signed-off-by: Andy Whitcroft <email address hidden>

Colin Watson (cjwatson) :
review: Approve
18745. By Andy Whitcroft on 2018-08-03

signing: fix brown paper bag moving openssl configuration body

Signed-off-by: Andy Whitcroft <email address hidden>

18746. By Andy Whitcroft on 2018-08-03

sigining: dedent initial definitions of openssl configuration fragments

Signed-off-by: Andy Whitcroft <email address hidden>

18747. By Andy Whitcroft on 2018-08-03

signing: tests -- standardise substring assertion

Signed-off-by: Andy Whitcroft <email address hidden>

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.