add test/factory_upgrade.py
authorNIIBE Yutaka <gniibe@fsij.org>
Wed, 19 Dec 2012 06:53:07 +0000 (15:53 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Wed, 19 Dec 2012 06:53:07 +0000 (15:53 +0900)
ChangeLog
src/Makefile.in
test/factory_upgrade.py [new file with mode: 0755]
tool/gnuk_token.py

index 3f1b2fb..5050e14 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2012-12-19  Niibe Yutaka  <gniibe@fsij.org>
 
+       * test/factory_upgrade.py: New.
+
+       * src/Makefile.in (USE_OPT): -O3 and -Os (was: -O2).
+
        * tool/gnuk_token.py (gnuk_token.stop_gnuk, gnuk_token.mem_info)
        (gnuk_token.download, gnuk_token.execute)
        (gnuk_token.cmd_get_challenge)
index 3f73460..3f5a094 100644 (file)
@@ -11,7 +11,7 @@ BOARD_DIR=@BOARD_DIR@
 
 # Compiler options here.
 ifeq ($(USE_OPT),)
-  USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
+  USE_OPT = -O3 -Os -ggdb -fomit-frame-pointer -falign-functions=16
 endif
 
 # C++ specific options here (added to USE_OPT).
diff --git a/test/factory_upgrade.py b/test/factory_upgrade.py
new file mode 100755 (executable)
index 0000000..2234a92
--- /dev/null
@@ -0,0 +1,111 @@
+#! /usr/bin/python
+
+"""
+factory_upgrade.py - a tool to install another firmware for Gnuk Token
+                     which is just shipped from factory
+
+Copyright (C) 2012 Free Software Initiative of Japan
+Author: NIIBE Yutaka <gniibe@fsij.org>
+
+This file is a part of Gnuk, a GnuPG USB Token implementation.
+
+Gnuk is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Gnuk is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+
+from gnuk_token import *
+import sys, binascii, time, os
+
+DEFAULT_PW3 = "12345678"
+BY_ADMIN = 3
+
+KEYNO_FOR_AUTH=2 
+
+def main(passwd, data_regnual, data_upgrade):
+    l = len(data_regnual)
+    if (l & 0x03) != 0:
+        data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
+    crc32code = crc32(data_regnual)
+    print "CRC32: %04x\n" % crc32code
+    data_regnual += pack('<I', crc32code)
+
+    rsa_raw_pubkey = rsa.integer_to_bytes_256(rsa.key[KEYNO_FOR_AUTH][7])
+
+    gnuk = get_gnuk_device()
+    gnuk.cmd_verify(BY_ADMIN, passwd)
+    gnuk.cmd_write_binary(1, rsa_raw_pubkey, False)
+
+    gnuk.cmd_select_openpgp()
+    challenge = gnuk.cmd_get_challenge()
+    digestinfo = binascii.unhexlify(SHA256_OID_PREFIX) + challenge
+    signed = rsa.compute_signature(KEYNO_FOR_AUTH, digestinfo)
+    signed_bytes = rsa.integer_to_bytes_256(signed)
+    gnuk.cmd_external_authenticate(signed_bytes)
+    gnuk.stop_gnuk()
+    mem_info = gnuk.mem_info()
+    print "%08x:%08x" % mem_info
+
+    print "Downloading flash upgrade program..."
+    gnuk.download(mem_info[0], data_regnual)
+    print "Run flash upgrade program..."
+    gnuk.execute(mem_info[0] + len(data_regnual) - 4)
+    #
+    time.sleep(3)
+    gnuk.reset_device()
+    del gnuk
+    gnuk = None
+    #
+    print "Wait 3 seconds..."
+    time.sleep(3)
+    # Then, send upgrade program...
+    reg = None
+    for dev in gnuk_devices_by_vidpid():
+        try:
+            reg = regnual(dev)
+            print "Device: ", dev.filename
+            break
+        except:
+            pass
+    mem_info = reg.mem_info()
+    print "%08x:%08x" % mem_info
+    print "Downloading the program"
+    reg.download(mem_info[0], data_upgrade)
+    reg.protect()
+    reg.finish()
+    reg.reset_device()
+    return 0
+
+if __name__ == '__main__':
+    if os.getcwd() != os.path.dirname(os.path.abspath(__file__)):
+        print "Please change working directory to: %s" % os.path.dirname(os.path.abspath(__file__))
+        exit(1)
+
+    import rsa_keys as rsa
+
+    passwd = DEFAULT_PW3
+    if len(sys.argv) > 1 and sys.argv[1] == '-p':
+        from getpass import getpass
+        passwd = getpass("Admin password: ")
+        sys.argv.pop(1)
+    filename_regnual = sys.argv[1]
+    filename_upgrade = sys.argv[2]
+    f = open(filename_regnual)
+    data_regnual = f.read()
+    f.close()
+    print "%s: %d" % (filename_regnual, len(data_regnual))
+    f = open(filename_upgrade)
+    data_upgrade = f.read()
+    f.close()
+    print "%s: %d" % (filename_upgrade, len(data_upgrade))
+    # First 4096-byte in data_upgrade is SYS, so, skip it.
+    main(passwd, data_regnual, data_upgrade[4096:])
index 78de09d..f60e6aa 100644 (file)
@@ -21,8 +21,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
 
 from struct import *
-import string
-import usb
+import string, binascii
+import usb, time
 
 # USB class, subclass, protocol
 CCID_CLASS = 0x0B
@@ -606,3 +606,12 @@ def get_gnuk_device():
     else:
         raise ValueError("Unknown ICC status", status)
     return icc
+
+SHA256_OID_PREFIX="3031300d060960864801650304020105000420"
+
+def UNSIGNED(n):
+    return n & 0xffffffff
+
+def crc32(bytestr):
+    crc = binascii.crc32(bytestr)
+    return UNSIGNED(crc)