chiark / gitweb /
support repo signing with a key on a smartcard
authorHans-Christoph Steiner <hans@eds.org>
Fri, 4 Apr 2014 04:05:22 +0000 (00:05 -0400)
committerHans-Christoph Steiner <hans@eds.org>
Mon, 7 Apr 2014 20:00:18 +0000 (16:00 -0400)
This assumes that the smartcard is already setup with a signing key.  init
does not generate a key on the smartcard, and skips genkey() if things are
configured to use a smartcard.

This also does not touch APK signing because that is a much more elaborate
question, since each app is signed by its own key.

examples/opensc-fdroid.cfg [new file with mode: 0644]
fdroidserver/init.py
fdroidserver/update.py
setup.py
tests/run-tests.sh

diff --git a/examples/opensc-fdroid.cfg b/examples/opensc-fdroid.cfg
new file mode 100644 (file)
index 0000000..bf3ef2f
--- /dev/null
@@ -0,0 +1,4 @@
+name = OpenSC
+description = SunPKCS11 w/ OpenSC Smart card Framework
+library = /usr/lib/opensc-pkcs11.so
+slotListIndex = 1
index 14d9434dfe7ad246847564b48d894f008731b4be..9571d401b4e4bbbebc1f969d775f272bfb629f4f 100644 (file)
@@ -19,6 +19,7 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import glob
 import hashlib
 import os
 import re
@@ -44,6 +45,16 @@ def write_to_config(key, value):
     with open('config.py', 'w') as f:
         f.writelines(data)
 
+def disable_in_config(key, value):
+    '''write a key/value to the local config.py, then comment it out'''
+    with open('config.py', 'r') as f:
+        data = f.read()
+    pattern = '\n[\s#]*' + key + '\s*=\s*"[^"]*"'
+    repl = '\n#' + key + ' = "' + value + '"'
+    data = re.sub(pattern, repl, data)
+    with open('config.py', 'w') as f:
+        f.writelines(data)
+
 
 def genpassword():
     '''generate a random password for when generating keys'''
@@ -196,7 +207,30 @@ def main():
     if options.distinguished_name:
         keydname = options.distinguished_name
         write_to_config('keydname', keydname)
-    if not os.path.isfile(keystore):
+    if keystore == 'NONE': # we're using a smartcard
+        write_to_config('repo_keyalias', '1')  # seems to be the default
+        disable_in_config('keypass', 'never used with smartcard')
+        write_to_config('smartcardoptions',
+                        ('-storetype PKCS11 -providerName SunPKCS11-OpenSC '
+                         + '-providerClass sun.security.pkcs11.SunPKCS11 '
+                         + '-providerArg opensc-fdroid.cfg'))
+        # find opensc-pkcs11.so
+        if not os.path.exists('opensc-fdroid.cfg'):
+            if os.path.exists('/usr/lib/opensc-pkcs11.so'):
+                opensc_so = '/usr/lib/opensc-pkcs11.so'
+            elif os.path.exists('/usr/lib64/opensc-pkcs11.so'):
+                opensc_so = '/usr/lib64/opensc-pkcs11.so'
+            else:
+                files = glob.glob('/usr/lib/' + os.uname()[4] + '-*-gnu/opensc-pkcs11.so')
+                if len(files) > 0:
+                    opensc_so = files[0]
+            with open(os.path.join(examplesdir, 'opensc-fdroid.cfg'), 'r') as f:
+                opensc_fdroid = f.read()
+            opensc_fdroid = re.sub('^library.*', 'library = ' + opensc_so, opensc_fdroid,
+                                   flags=re.MULTILINE)
+            with open('opensc-fdroid.cfg', 'w') as f:
+                f.write(opensc_fdroid)
+    elif not os.path.exists(keystore):
         # no existing or specified keystore, generate the whole thing
         keystoredir = os.path.dirname(keystore)
         if not os.path.exists(keystoredir):
index c386499a554c3654a0b00d9b7836248391e29e49..f9d4248674deb42b839c87cf473cfd183f37ada3 100644 (file)
@@ -796,12 +796,15 @@ def make_index(apps, apks, repodir, archive, categories):
             sys.exit(1)
 
         # Sign the index...
-        p = FDroidPopen(['jarsigner', '-keystore', config['keystore'],
-            '-storepass:file', config['keystorepassfile'],
-            '-keypass:file', config['keypassfile'],
-            '-digestalg', 'SHA1', '-sigalg', 'MD5withRSA',
-            os.path.join(repodir, 'index.jar') , config['repo_keyalias']]
-            + config['smartcardoptions'])
+        args = ['jarsigner', '-keystore', config['keystore'],
+                '-storepass:file', config['keystorepassfile'],
+                '-digestalg', 'SHA1', '-sigalg', 'MD5withRSA',
+                os.path.join(repodir, 'index.jar'), config['repo_keyalias']]
+        if config['keystore'] == 'NONE':
+            args += config['smartcardoptions']
+        else:  # smardcards never use -keypass
+            args += ['-keypass:file', config['keypassfile']]
+        p = FDroidPopen(args)
         # TODO keypass should be sent via stdin
         if p.returncode != 0:
             logging.info("Failed to sign index")
index 3bfea0415ff08c8648f52e1bafb253199fc7de4e..35ecc8e5e6eb6f369a833553afe51315824db08b 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -23,6 +23,7 @@ setup(name='fdroidserver',
          [ 'buildserver/config.buildserver.py',
            'examples/config.py',
            'examples/makebs.config.py',
+           'examples/opensc-fdroid.cfg',
            'examples/fdroid-icon.png']),
         ('fdroidserver/getsig', ['fdroidserver/getsig/getsig.class'])
         ],
index dbe62eed642017d8165eda0c16173a3918958a34..c75a2f02119d885d6bd1577aaa74cc85458a6592 100755 (executable)
@@ -49,3 +49,13 @@ $fdroid update -c
 $fdroid update
 test -e repo/index.xml
 test -e repo/index.jar
+
+
+#------------------------------------------------------------------------------#
+# setup a new repo from scratch with a HSM/smartcard
+
+REPOROOT=`mktemp --directory --tmpdir=$WORKSPACE`
+cd $REPOROOT
+$fdroid init --keystore NONE
+test -e opensc-fdroid.cfg
+test ! -e NONE