Support upgrade with passwd
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 30 Jun 2015 04:38:16 +0000 (13:38 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 30 Jun 2015 06:47:55 +0000 (15:47 +0900)
ChangeLog
NEWS
chopstx
src/main.c
src/neug.ld.in
tool/neug_check.py
tool/neug_upgrade.py

index 50d981f..801696e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2015-06-30  Niibe Yutaka  <gniibe@fsij.org>
 
+       * tool/neug_check.py: Fix raise and print statements.
+
+       * tool/neug_upgrade.py: Support upgrade with passwd.
+       (neug.set_passwd): New.
+
+       * src/main.c (USB_NEUG_SET_PASSWD): New.
+       (set_passwd): New.
+       (usb_cb_ctrl_write_finish, usb_cb_setup): Handle
+       USB_NEUG_SET_PASSWD and USB_NEUG_EXIT with passwd.
+
+       * src/neug.ld.in (flash): A page for passwd.
+
        * src/config.h.in (@SERIALNO_STR_LEN_DEFINE@): Rename.
        * src/configure (SERIALNO_STR_LEN_DEFINE): Rename.
 
diff --git a/NEWS b/NEWS
index 7fc2c60..000d977 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,16 @@
 NeuG NEWS - User visible changes
 
+* Major changes in NeuG 1.0.2
+
+  Released 2015-09-XX, by NIIBE Yutaka
+
+** Upgrade of firmware enhancement
+The process is protected by password.
+
+** Upgrade of Chopstx
+We use Chopstx 0.06.
+
+
 * Major changes in NeuG 1.0.1
 
   Released 2015-01-29, by NIIBE Yutaka
diff --git a/chopstx b/chopstx
index 6665723..43bd3bc 160000 (submodule)
--- a/chopstx
+++ b/chopstx
@@ -1 +1 @@
-Subproject commit 666572315430ff5e545b32dc9f97fa70a236a6bd
+Subproject commit 43bd3bcefd6dbd28e3fd68ca8ff6b9a877009774
index c59df0a..26c2179 100644 (file)
@@ -216,9 +216,31 @@ static const uint8_t *const mem_info[] = { &_regnual_start,  &__heap_end__, };
 #define USB_FSIJ_MEMINFO         0
 #define USB_FSIJ_DOWNLOAD        1
 #define USB_FSIJ_EXEC            2
+#define USB_NEUG_SET_PASSWD    253
 #define USB_NEUG_GET_INFO      254
 #define USB_NEUG_EXIT          255 /* Ask to exit and to receive reGNUal */
 
+uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
+  0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+static uint8_t passwd_data[33];
+
+#define DEFAULT_PASSWD "12345678"
+#define DEFAULT_PASSWD_LEN 8
+
+static void set_passwd (void)
+{
+  flash_unlock ();
+  if (neug_passwd[0] != 0xff)
+    flash_erase_page ((uint32_t)neug_passwd);
+  if (passwd_data[0] == DEFAULT_PASSWD_LEN
+      && !memcmp (passwd_data + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
+    return;
+  flash_write ((uint32_t)neug_passwd, passwd_data, passwd_data[0] + 1);
+}
 
 static uint32_t rbit (uint32_t v)
 {
@@ -252,10 +274,9 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
 {
   uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
 
-  if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)
-      && USB_SETUP_SET (req) && len == 0)
+  if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req))
     {
-      if (req_no == USB_FSIJ_EXEC)
+      if (req_no == USB_FSIJ_EXEC && len == 0)
        {
          chopstx_mutex_lock (&usb_mtx);
          if (fsij_device_state == FSIJ_DEVICE_EXITED)
@@ -265,17 +286,18 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
            }
          chopstx_mutex_unlock (&usb_mtx);
        }
+      else if (req_no == USB_NEUG_SET_PASSWD)
+       set_passwd ();
       else if (req_no == USB_NEUG_EXIT)
        {
-         /* Force exit from the main loop.  */
-         if (wait_usb_connection)
-           {
-             wait_usb_connection = 0;
-             chopstx_wakeup_usec_wait (main_thd);
-           }
-         else
+         if ((neug_passwd[0] == 0xff && passwd_data[0] == DEFAULT_PASSWD_LEN
+              && !memcmp (passwd_data + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
+             || (neug_passwd[0] == passwd_data[0]
+                 && !memcmp (neug_passwd+1, passwd_data+1, neug_passwd[0])))
            {
              chopstx_mutex_lock (&usb_mtx);
+             fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
+             chopstx_wakeup_usec_wait (main_thd);
              chopstx_cond_signal (&cnd_usb);
              chopstx_mutex_unlock (&usb_mtx);
            }
@@ -291,10 +313,7 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
       if (wait_usb_connection)
        {                       /* It is waiting a connection.  */
          if (connected)        /* It's now connected.  */
-           {
-             wait_usb_connection = 0;
-             chopstx_wakeup_usec_wait (main_thd);
-           }
+           chopstx_wakeup_usec_wait (main_thd);
        }
       else
        chopstx_cond_signal (&cnd_usb);
@@ -359,6 +378,13 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
        {
          if (req_no == USB_FSIJ_MEMINFO)
            {
+             chopstx_mutex_lock (&usb_mtx);
+             if (fsij_device_state != FSIJ_DEVICE_EXITED)
+               {
+                 chopstx_mutex_unlock (&usb_mtx);
+                 return USB_UNSUPPORT;
+               }
+             chopstx_mutex_unlock (&usb_mtx);
              usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
              return USB_SUCCESS;
            }
@@ -424,7 +450,13 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
 
              return download_check_crc32 ((uint32_t *)addr);
            }
-         else if (req_no == USB_NEUG_EXIT && len == 0)
+         else if (req_no == USB_NEUG_SET_PASSWD && len <= 32)
+           {
+             passwd_data[0] = len;
+             usb_lld_set_data_to_recv (passwd_data + 1, len);
+             return USB_SUCCESS;
+           }
+         else if (req_no == USB_NEUG_EXIT && len <= 32)
            {
              chopstx_mutex_lock (&usb_mtx);
              if (fsij_device_state != FSIJ_DEVICE_RUNNING)
@@ -432,12 +464,10 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
                  chopstx_mutex_unlock (&usb_mtx);
                  return USB_UNSUPPORT;
                }
-
-             fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
-             chopstx_wakeup_usec_wait (main_thd);
-             chopstx_cond_signal (&cnd_usb);
              chopstx_mutex_unlock (&usb_mtx);
 
+             passwd_data[0] = len;
+             usb_lld_set_data_to_recv (passwd_data + 1, len);
              return USB_SUCCESS;
            }
        }
index 99d2def..aa34050 100644 (file)
@@ -140,6 +140,7 @@ SECTIONS
     .fill_ffff :
     {
         . = ALIGN (@FLASH_PAGE_SIZE@);
+       *(.passwd)
     } > flash =0xffffffff
 }
 
index 0733218..80a0af9 100755 (executable)
@@ -44,9 +44,9 @@ class neug(object):
         interface: usb.Interface object representing the interface and altenate setting.
         """
         if interface.interfaceClass !=COM_CLASS:
-            raise ValueError, "Wrong interface class"
+            raise ValueError("Wrong interface class")
         if interface.interfaceSubClass != COM_SUBCLASS:
-            raise ValueError, "Wrong interface sub class"
+            raise ValueError("Wrong interface sub class")
         self.__devhandle = device.open()
         # self.__devhandle.claimInterface(interface)
         # self.__devhandle.setAltInterface(interface)
@@ -97,27 +97,27 @@ def main():
     for (dev, config, intf) in com_devices():
         try:
             com = neug(dev, config, intf)
-            print "Device: ", dev.filename
-            print "Configuration: ", config.value
-            print "Interface: ", intf.interfaceNumber
+            print("Device: %s" % dev.filename)
+            print("Configuration: %d" % config.value)
+            print("Interface: %d" % intf.interfaceNumber)
             break
         except:
             pass
     if not com:
-        raise ValueError, "No NeuG Device Present"
-    print
+        raise ValueError("No NeuG Device Present")
+    print("")
     for i in range(1,7):
         s = com.get_string(i, 512)
-        print "%9s: %s" % (field[i], s)
-    print
-    print "mode: %s" % com.get_mode()
-    print "Repeat errors: %d" % com.get_info(2)
-    print "PP 64  errors: %d" % com.get_info(3)
-    print "PP 4k  errors: %d" % com.get_info(4)
-    print "Total  errors: %d" % com.get_info(1)
-    print "Repeat max counts: %d" % com.get_info(5)
-    print "PP 64  max counts: %d" % com.get_info(6)
-    print "PP 4k  max counts: %d" % com.get_info(7)
+        print("%9s: %s" % (field[i], s))
+    print("")
+    print("mode: %s" % com.get_mode()
+    print("Repeat errors: %d" % com.get_info(2))
+    print("PP 64  errors: %d" % com.get_info(3))
+    print("PP 4k  errors: %d" % com.get_info(4))
+    print("Total  errors: %d" % com.get_info(1))
+    print("Repeat max counts: %d" % com.get_info(5))
+    print("PP 64  max counts: %d" % com.get_info(6))
+    print("PP 4k  max counts: %d" % com.get_info(7))
     return 0
 
 
index 48d9a42..7a18af0 100755 (executable)
@@ -3,7 +3,7 @@
 """
 neug_upgrade.py - a tool to upgrade firmware of Gnuk Token / NeuG device
 
-Copyright (C) 2012 Free Software Initiative of Japan
+Copyright (C) 2012, 2015 Free Software Initiative of Japan
 Author: NIIBE Yutaka <gniibe@fsij.org>
 
 This file is a part of NeuG, a TRNG implementation.
@@ -24,8 +24,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from struct import *
 import sys, time, os, binascii, string
+from getpass import getpass
 
-# INPUT: binary file
+DEFAULT_PW3 = "12345678"
+
+# INPUT: <regnual binary file> <new firmware binary file>
 
 # Assume only single NeuG device is attached to computer
 
@@ -42,7 +45,7 @@ class regnual(object):
         intf_alt = conf.interfaces[0]
         intf = intf_alt[0]
         if intf.interfaceClass != 0xff:
-            raise ValueError, "Wrong interface class"
+            raise ValueError("Wrong interface class")
         self.__devhandle = dev.open()
         try:
             self.__devhandle.setConfiguration(conf)
@@ -59,15 +62,16 @@ class regnual(object):
         end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
         return (start, end)
 
-    def download(self, start, data):
+    def download(self, start, data, verbose=False):
         addr = start
         addr_end = (start + len(data)) & 0xffffff00
         i = (addr - 0x08000000) / 0x100
         j = 0
-        print "start %08x" % addr
-        print "end   %08x" % addr_end
+        print("start %08x" % addr)
+        print("end   %08x" % addr_end)
         while addr < addr_end:
-            print "# %08x: %d: %d : %d" % (addr, i, j, 256)
+            if verbose:
+                print("# %08x: %d: %d : %d" % (addr, i, j, 256))
             self.__devhandle.controlMsg(requestType = 0x40, request = 1,
                                         value = 0, index = 0,
                                         buffer = data[j*256:j*256+256],
@@ -78,7 +82,7 @@ class regnual(object):
                                               timeout = 10000)
             r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
             if (crc32code ^ r_value) != 0xffffffff:
-                print "failure"
+                print("failure")
             self.__devhandle.controlMsg(requestType = 0x40, request = 3,
                                         value = i, index = 0,
                                         buffer = None,
@@ -89,13 +93,14 @@ class regnual(object):
                                               timeout = 10000)
             r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
             if r_value == 0:
-                print "failure"
+                print("failure")
             i = i+1
             j = j+1
             addr = addr + 256
         residue = len(data) % 256
         if residue != 0:
-            print "# %08x: %d : %d" % (addr, i, residue)
+            if verbose:
+                print("# %08x: %d : %d" % (addr, i, residue))
             self.__devhandle.controlMsg(requestType = 0x40, request = 1,
                                         value = 0, index = 0,
                                         buffer = data[j*256:],
@@ -106,7 +111,7 @@ class regnual(object):
                                               timeout = 10000)
             r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
             if (crc32code ^ r_value) != 0xffffffff:
-                print "failure"
+                print("failure")
             self.__devhandle.controlMsg(requestType = 0x40, request = 3,
                                         value = i, index = 0,
                                         buffer = None,
@@ -117,7 +122,7 @@ class regnual(object):
                                               timeout = 10000)
             r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
             if r_value == 0:
-                print "failure"
+                print("failure")
 
     def protect(self):
         self.__devhandle.controlMsg(requestType = 0x40, request = 4,
@@ -129,7 +134,7 @@ class regnual(object):
                                           timeout = 10000)
         r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
         if r_value == 0:
-            print "protection failure"
+            print("protection failure")
 
     def finish(self):
         self.__devhandle.controlMsg(requestType = 0x40, request = 5,
@@ -152,9 +157,9 @@ class neug(object):
         interface: usb.Interface object representing the interface and altenate setting.
         """
         if interface.interfaceClass !=COM_CLASS:
-            raise ValueError, "Wrong interface class"
+            raise ValueError("Wrong interface class")
         if interface.interfaceSubClass != COM_SUBCLASS:
-            raise ValueError, "Wrong interface sub class"
+            raise ValueError("Wrong interface sub class")
         self.__devhandle = device.open()
         # self.__devhandle.claimInterface(interface)
         # self.__devhandle.setAltInterface(interface)
@@ -174,9 +179,15 @@ class neug(object):
         except:
             pass
 
-    def stop_neug(self):
+    def set_passwd(self, passwd):
+        self.__devhandle.controlMsg(requestType = 0x40, request = 253,
+                                    value = 0, index = 0, buffer = passwd,
+                                    timeout = 1000)
+        return
+
+    def stop_neug(self, passwd):
         self.__devhandle.controlMsg(requestType = 0x40, request = 255,
-                                    value = 0, index = 0, buffer = None,
+                                    value = 0, index = 0, buffer = passwd,
                                     timeout = 1000)
         # self.__devhandle.releaseInterface()
         # self.__devhandle.setConfiguration(0)
@@ -190,15 +201,16 @@ class neug(object):
         end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
         return (start, end)
 
-    def download(self, start, data):
+    def download(self, start, data, verbose=False):
         addr = start
         addr_end = (start + len(data)) & 0xffffff00
         i = (addr - 0x20000000) / 0x100
         j = 0
-        print "start %08x" % addr
-        print "end   %08x" % addr_end
+        print("start %08x" % addr)
+        print("end   %08x" % addr_end)
         while addr < addr_end:
-            print "# %08x: %d : %d" % (addr, i, 256)
+            if verbose:
+                print("# %08x: %d : %d" % (addr, i, 256))
             self.__devhandle.controlMsg(requestType = 0x40, request = 1,
                                         value = i, index = 0,
                                         buffer = data[j*256:j*256+256],
@@ -208,7 +220,7 @@ class neug(object):
             addr = addr + 256
         residue = len(data) % 256
         if residue != 0:
-            print "# %08x: %d : %d" % (addr, i, residue)
+            print("# %08x: %d : %d" % (addr, i, residue))
             self.__devhandle.controlMsg(requestType = 0x40, request = 1,
                                         value = i, index = 0,
                                         buffer = data[j*256:],
@@ -225,7 +237,7 @@ def compare(data_original, data_in_device):
     i = 0 
     for d in data_original:
         if ord(d) != data_in_device[i]:
-            raise ValueError, "verify failed at %08x" % i
+            raise ValueError("verify failed at %08x" % i)
         i += 1
 
 def com_devices():
@@ -244,7 +256,7 @@ def com_devices():
 USB_VENDOR_FSIJ=0x234b
 USB_PRODUCT_GNUK=0x0000
 
-def gnuk_devices():
+def gnuk_devices_by_vidpid():
     busses = usb.busses()
     for bus in busses:
         devices = bus.devices
@@ -268,33 +280,34 @@ def crc32(bytestr):
     crc = binascii.crc32(bytestr)
     return UNSIGNED(crc)
 
-def main(data_regnual, data_upgrade):
+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
+    print("CRC32: %04x\n" % crc32code)
     data_regnual += pack('<I', crc32code)
     com = None
     for (dev, config, intf) in com_devices():
         try:
             com = neug(dev, config, intf)
-            print "Device: ", dev.filename
-            print "Configuration: ", config.value
-            print "Interface: ", intf.interfaceNumber
+            print("Device: %s" % dev.filename)
+            print("Configuration: %d" % config.value)
+            print("Interface: %d" % intf.interfaceNumber)
             break
         except:
             pass
     if not com:
-        raise ValueError, "No NeuG Device Present"
-    com.stop_neug()
-    com.detach_driver()
+        raise ValueError("No NeuG Device Present")
+    com.stop_neug(passwd)
     time.sleep(1.500)
     mem_info = com.mem_info()
-    print "%08x:%08x" % mem_info
-    print "Downloading flash upgrade program..."
+    print("%08x:%08x" % mem_info)
+    com.detach_driver()
+    time.sleep(1.500)
+    print("Downloading flash upgrade program...")
     com.download(mem_info[0], data_regnual)
-    print "Run flash upgrade program..."
+    print("Run flash upgrade program...")
     com.execute(mem_info[0] + len(data_regnual) - 4)
     #
     time.sleep(3)
@@ -302,20 +315,20 @@ def main(data_regnual, data_upgrade):
     del com
     com = None
     #
-    print "Wait 3 seconds..."
+    print("Wait 3 seconds...")
     time.sleep(3)
     # Then, send upgrade program...
     reg = None
-    for dev in gnuk_devices():
+    for dev in gnuk_devices_by_vidpid():
         try:
             reg = regnual(dev)
-            print "Device: ", dev.filename
+            print("Device: %s" % dev.filename)
             break
         except:
             pass
     mem_info = reg.mem_info()
-    print "%08x:%08x" % mem_info
-    print "Downloading the program"
+    print("%08x:%08x" % mem_info)
+    print("Downloading the program")
     reg.download(mem_info[0], data_upgrade)
     reg.protect()
     reg.finish()
@@ -324,14 +337,40 @@ def main(data_regnual, data_upgrade):
 
 
 if __name__ == '__main__':
+    passwd = None
+    if len(sys.argv) == 2 and sys.argv[1] == '-s': # S for set passwd
+        passwd = getpass("Admin password: ")
+        com = None
+        for (dev, config, intf) in com_devices():
+            try:
+                com = neug(dev, config, intf)
+                print("Device: %s" % dev.filename)
+                print("Configuration: %d" % config.value)
+                print("Interface: %d" % intf.interfaceNumber)
+                break
+            except:
+                pass
+        if not com:
+            raise ValueError("No NeuG Device Present")
+        com.set_passwd(passwd)
+        exit(0)
+    while len(sys.argv) > 3:
+        option = sys.argv[1]
+        sys.argv.pop(1)
+        if option == '-f':      # F for Factory setting
+            passwd = DEFAULT_PW3
+        else:
+            raise ValueError("unknown option", option)
+    if not passwd:
+        passwd = getpass("Admin password: ")
     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))
+    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))
-    main(data_regnual, data_upgrade[4096:])
+    print("%s: %d" % (filename_upgrade, len(data_upgrade)))
+    main(passwd, data_regnual, data_upgrade[4096:])