← Back to team overview

launchpad-reviewers team mailing list archive

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

 

Andy Whitcroft has proposed merging lp:~apw/launchpad/signing-kmod-extended-key-usage into lp:launchpad.

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.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1774746 in Launchpad itself: "launchpad archive-generated kmod signing keys should use extendedKeyUsage 1.3.6.1.4.1.2312.16.1.2"
  https://bugs.launchpad.net/launchpad/+bug/1774746

For more details, see:
https://code.launchpad.net/~apw/launchpad/signing-kmod-extended-key-usage/+merge/352305
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~apw/launchpad/signing-kmod-extended-key-usage into lp:launchpad.
=== 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 14:13:53 +0000
@@ -242,6 +242,41 @@
         cmdl = ["sbsign", "--key", key, "--cert", cert, image]
         return self.callLog("UEFI signing", cmdl)
 
+    openssl_config_opal = """
+        [ req ]
+        default_bits = 4096
+        distinguished_name = req_distinguished_name
+        prompt = no
+        string_mask = utf8only
+        x509_extensions = myexts
+
+        [ req_distinguished_name ]
+        CN = {common_name}
+
+        [ myexts ]
+        basicConstraints=critical,CA:FALSE
+        keyUsage=digitalSignature
+        subjectKeyIdentifier=hash
+        authorityKeyIdentifier=keyidb
+        """
+
+    openssl_config_kmod = openssl_config_opal + """
+        # codeSigning:  specifies that this key is used to sign code.
+        # 1.3.6.1.4.1.2312.16.1.2:  defines this key as used for
+        #   module signing only. See https://lkml.org/lkml/2015/8/26/741.
+        extendedKeyUsage        = codeSigning,1.3.6.1.4.1.2312.16.1.2
+        """
+
+    def generateOpensslConfig(self, key_type, common_name):
+        if key_type == 'Kmod':
+            genkey_tmpl = self.openssl_config_kmod
+        elif key_type == 'Opal':
+            genkey_tmpl = self.openssl_config_opal
+        else:
+            raise ValueError("unknown key_type " + key_type)
+
+        return textwrap.dedent(genkey_tmpl.format(common_name=common_name))
+
     def generatePemX509Pair(self, key_type, pem_filename, x509_filename):
         """Generate new pem/x509 key pairs."""
         directory = os.path.dirname(pem_filename)
@@ -255,28 +290,13 @@
         old_mask = os.umask(0o077)
         try:
             with tempfile.NamedTemporaryFile(suffix='.keygen') as tf:
-                genkey_text = textwrap.dedent("""\
-                    [ req ]
-                    default_bits = 4096
-                    distinguished_name = req_distinguished_name
-                    prompt = no
-                    string_mask = utf8only
-                    x509_extensions = myexts
-
-                    [ req_distinguished_name ]
-                    CN = %s
-
-                    [ myexts ]
-                    basicConstraints=critical,CA:FALSE
-                    keyUsage=digitalSignature
-                    subjectKeyIdentifier=hash
-                    authorityKeyIdentifier=keyid
-                    """ % common_name)
-
+                genkey_text = self.generateOpensslConfig(key_type, common_name)
                 print(genkey_text, file=tf)
 
                 # Close out the underlying file so we know it is complete.
                 tf.file.close()
+                from shutil import copyfile
+                copyfile(tf.name, '/home/apw/KEYGEN-' + key_type)
 
                 new_key_cmd = [
                     'openssl', 'req', '-new', '-nodes', '-utf8', '-sha512',

=== 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 14:13:53 +0000
@@ -8,6 +8,7 @@
 __metaclass__ = type
 
 import os
+import re
 import stat
 import tarfile
 
@@ -555,6 +556,21 @@
             ]
         self.assertEqual(expected_cmd, args)
 
+    def test_correct_kmod_openssl_config(self):
+        # Check that calling generateOpensslConfig() will return an appropriate
+        # openssl configuration.
+        upload = SigningUpload()
+        text = upload.generateOpensslConfig('Kmod', 'something-unique')
+
+        cn_re = re.compile(r'\bCN\s*=\s*something-unique\b')
+        eku_re = re.compile(
+            r'\bextendedKeyUsage\s*=\s*'
+            r'codeSigning,1.3.6.1.4.1.2312.16.1.2\s*\b')
+
+        self.assertTrue('[ req ]' in text)
+        self.assertIsNotNone(cn_re.search(text))
+        self.assertIsNotNone(eku_re.search(text))
+
     def test_correct_kmod_signing_command_executed(self):
         # Check that calling signKmod() will generate the expected command
         # when appropriate keys are present.
@@ -621,6 +637,18 @@
             ]
         self.assertEqual(expected_cmd, args)
 
+    def test_correct_opal_openssl_config(self):
+        # Check that calling generateOpensslConfig() will return an appropriate
+        # openssl configuration.
+        upload = SigningUpload()
+        text = upload.generateOpensslConfig('Opal', 'something-unique')
+
+        cn_re = re.compile(r'\bCN\s*=\s*something-unique\b')
+
+        self.assertTrue('[ req ]' in text)
+        self.assertIsNotNone(cn_re.search(text))
+        self.assertFalse('extendedKeyUsage' in text)
+
     def test_correct_opal_signing_command_executed(self):
         # Check that calling signOpal() will generate the expected command
         # when appropriate keys are present.


Follow ups