fix cancellation
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 10 Sep 2015 05:14:37 +0000 (14:14 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 10 Sep 2015 05:14:37 +0000 (14:14 +0900)
ChangeLog
doc/note/firmware-update-2 [new file with mode: 0644]
src/call-rsa.c
src/openpgp-do.c
src/openpgp.c

index 788c300..c74f953 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,15 @@
+2015-09-10  Niibe Yutaka  <gniibe@fsij.org>
+
+       * src/call-rsa.c (rsa_cleanup): New.
+       (rsa_sign, rsa_decrypt, rsa_genkey): Alloc cancellation.
+       * src/openpgp.c (cmd_pso, cmd_internal_authenticate): Cancellation
+       is handled by each functions in case of RSA.
+
 2015-09-09  Niibe Yutaka  <gniibe@fsij.org>
 
        * src/openpgp.c (process_command_apdu): Protect command execution
        against cancelling the execution thread.
        (cmd_pso, cmd_internal_authenticate): Allow cancellation.
-       * src/openpgp-do.c (gpg_do_keygen): Allow cancellation.
 
        * src/main.c (main): Handle LED_USB_RESET.
 
diff --git a/doc/note/firmware-update-2 b/doc/note/firmware-update-2
new file mode 100644 (file)
index 0000000..6f78599
--- /dev/null
@@ -0,0 +1,131 @@
+Please refer:
+
+    How can I reflash FST-01 with SWD port?:
+    http://www.gniibe.org/FST-01/q_and_a/swd-debugger.html
+
+
+Installing newer version of Gnuk onto FST-01 with Gnuk 1.0.1
+============================================================
+
+Please note that the feature of firmware upgrade is somewhat
+experimental.  I haven't got any success reports yet, but it's only
+used by me, so far.  When you will get some failure during your
+firmware installation, you will need SWD debugger.  YOU HAVE BEEN
+WARNED.  It is best to try firmware upgrade after you get a SWD
+debugger.
+
+
+The firmare upgrade feature of Gnuk
+------------------------------------
+
+Gnuk supports firmware upgrade by reGNUal.  It works in the following
+steps.
+
+1. User registers RSA public key to Gnuk Token for firmware upgrade
+
+2. When User wants firmware upgrade, user sends
+   the GET_CHALLENGE command then the EXTERNAL_AUTHENTICATE command
+   to Gnuk Token from host PC to authenticate.
+   The EXTERNAL_AUTHENTICATE command message consists of
+   signature (of challenge) by corresponding RSA private key.
+
+3. When Gnuk Token receives the EXTERNAL_AUTHENTICATE command message
+   and validates signature successfully, Gnuk finishes its normal
+   operation and goes to enter mode of loading special program onto RAM.
+
+4. Host PC sends reflashing program (reGNUal) to Gnuk Token.
+
+5. Gnuk clears up all content of flash ROM (but first 4KiB of system)
+   at the end of receiving special program and transfers its control
+   to reGNUal.
+
+6. reGNUal on Gnuk Token receives new firmware image from host PC and writes
+   to each page.
+
+7. Done.
+
+
+Host PC setting for Gnuk
+------------------------
+
+You need proper configuration for permission of Gnuk Token (udev
+setting).  It should have lines something like: ::
+
+  # Gnuk Token by FSIJ
+
+  SUBSYSTEMS=="usb", ACTION=="add", \
+    ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
+    ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
+
+I have those lines in /etc/udev/rules.d/69-gnuk.rules.
+
+
+Building another version (newer) of Gnuk
+----------------------------------------
+
+Please see README of Gnuk for detail, but it's like configure
+and make:  ::
+
+  $ pwd
+  /home/user/src/gnuk
+  $ cd src
+  $ ./configure --vidpid=234b:0000
+  $ make
+
+Please take care of configure options.  The default target in 1.0.x
+series is Olimex STM32 H103 (not FST-01).  The default target in 1.1.8
+is FST-01.
+
+
+Then you get build/gnuk.elf and build/gnuk.bin.
+
+Invoking configure with FSIJ's USB ID (234b:0000) means that you are
+using FSIJ's USB ID (for reGNUal in this case).  Please note that FSIJ
+only allows use of its USB ID for specific situations.  Please read
+README of Gnuk about that.
+
+
+Bulding reGNUal
+---------------
+
+You need to compile reGNUal. ::
+
+  $ cd ../regnual
+  $ make
+
+Then, you should have regnual.bin.  Note that 'configure' of Gnuk
+itself is needed before compiling reGNUal.
+
+
+upgrade_by_passwd.py
+--------------------
+
+In the source code distribution of 1.0.4 (or current development
+version) of Gnuk, there is a tool named 'upgrade_by_passwd.py'.
+
+This is an easy tool to hide lengthy steps from user and to allow user
+firmware upgrade only by password of Gnuk Token.
+
+Before running the script, you need to kill scdaemon: ::
+
+  $ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
+
+The command line invokation above assumes that you properly configure
+your environment for Gnuk Token.
+
+
+How to run the script: ::
+
+  $ cd tool
+  $ ./upgrade_by_passwd.py ../regnual/regnual.bin ../src/build/gnuk.bin
+
+Then, the script on your host PC invoke the steps described above, and
+you will get new version of Gnuk installed.
+
+You can also specify -p option to enter your password (other than
+factory setting).
+
+If you already have configured another upgrade key installed, you can
+specify different slot by -k ``<slot_no>`` option.  SLOT_NO can be 0
+to 3.
+-- 
index 43b6b26..0dd79f0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
  *
- * Copyright (C) 2010, 2011, 2012, 2013, 2014
+ * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
  *               Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
@@ -25,6 +25,8 @@
 #include <stdint.h>
 #include <string.h>
 #include <stdlib.h>
+#include <chopstx.h>
+
 #include "config.h"
 
 #include "gnuk.h"
 #include "polarssl/rsa.h"
 
 static rsa_context rsa_ctx;
+static struct chx_cleanup clp;
+
+sttic void
+rsa_cleanup (void *arg)
+{
+  free (arg);
+  rsa_free (&rsa_ctx);
+}
+
 
 int
 rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
@@ -66,12 +77,20 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
   mpi_free (&P1);  mpi_free (&Q1);  mpi_free (&H);
   if (ret == 0)
     {
-      DEBUG_INFO ("RSA sign...");
+      int cs;
 
+      DEBUG_INFO ("RSA sign...");
+      clp.next = NULL;
+      clp.routine = rsa_cleanup;
+      clp.arg = NULL;
+      chopstx_cleanup_push (&clp);
+      cs = chopstx_setcancelstate (0); /* Allow cancellation.  */
       ret = rsa_rsassa_pkcs1_v15_sign (&rsa_ctx, NULL, NULL,
                                       RSA_PRIVATE, SIG_RSA_RAW,
                                       msg_len, raw_message, temp);
       memcpy (output, temp, pubkey_len);
+      chopstx_setcancelstate (cs);
+      chopstx_cleanup_pop (&clp);
     }
 
   rsa_free (&rsa_ctx);
@@ -150,10 +169,19 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
   mpi_free (&P1);  mpi_free (&Q1);  mpi_free (&H);
   if (ret == 0)
     {
+      int cs;
+
       DEBUG_INFO ("RSA decrypt ...");
+      clp.next = NULL;
+      clp.routine = rsa_cleanup;
+      clp.arg = NULL;
+      chopstx_cleanup_push (&clp);
+      cs = chopstx_setcancelstate (0); /* Allow cancellation.  */
       ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
                                         RSA_PRIVATE, output_len_p, input,
                                         output, MAX_RES_APDU_DATA_SIZE);
+      chopstx_setcancelstate (cs);
+      chopstx_cleanup_pop (&clp);
     }
 
   rsa_free (&rsa_ctx);
@@ -213,6 +241,8 @@ rsa_genkey (int pubkey_len)
   uint8_t *p = p_q_modulus;
   uint8_t *q = p_q_modulus + pubkey_len / 2;
   uint8_t *modulus = p_q_modulus + pubkey_len;
+  int cs;
+
   extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
                        void *p_rng);
   extern void neug_flush (void);
@@ -222,12 +252,19 @@ rsa_genkey (int pubkey_len)
 
   neug_flush ();
   prng_seed (random_gen, &index);
-
   rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
+
+  clp.next = NULL;
+  clp.routine = rsa_cleanup;
+  clp.arg = (void *)p_q_modulus;
+  chopstx_cleanup_push (&clp);
+  cs = chopstx_setcancelstate (0); /* Allow cancellation.  */
   MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
                        RSA_EXPONENT) );
   if (ret != 0)
     {
+      chopstx_setcancelstate (cs);
+      chopstx_cleanup_pop (&clp);
       free (p_q_modulus);
       rsa_free (&rsa_ctx);
       return NULL;
@@ -238,6 +275,8 @@ rsa_genkey (int pubkey_len)
   MPI_CHK( mpi_write_binary (&rsa_ctx.N, modulus, pubkey_len) );
 
  cleanup:
+  chopstx_setcancelstate (cs);
+  chopstx_cleanup_pop (&clp);
   rsa_free (&rsa_ctx);
   if (ret != 0)
       return NULL;
index 78cb180..e18f42d 100644 (file)
@@ -25,7 +25,6 @@
 #include <stdint.h>
 #include <string.h>
 #include <stdlib.h>
-#include <chopstx.h>
 
 #include "config.h"
 
@@ -2060,10 +2059,7 @@ gpg_do_keygen (uint8_t kk_byte)
 
   if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
     {
-      int cs = chopstx_setcancelstate (0); /* Allow cancellation.  */
-      /* XXX: We need to free up the allocated memory on cancellation.  */
       p_q_modulus = rsa_genkey (prvkey_len);
-      chopstx_setcancelstate (cs);
       if (p_q_modulus == NULL)
        {
          GPG_MEMORY_FAILURE ();
index c1e9693..0c5b8ed 100644 (file)
@@ -854,11 +854,9 @@ cmd_pso (void)
 
          DEBUG_BINARY (kd[GPG_KEY_FOR_SIGNING].data, pubkey_len);
 
-         cs = chopstx_setcancelstate (0);
          result_len = pubkey_len;
          r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
                        &kd[GPG_KEY_FOR_SIGNING], pubkey_len);
-         chopstx_setcancelstate (cs);
        }
       else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
        {
@@ -939,10 +937,8 @@ cmd_pso (void)
              GPG_CONDITION_NOT_SATISFIED ();
              return;
            }
-         cs = chopstx_setcancelstate (0);
          r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
                           &kd[GPG_KEY_FOR_DECRYPTION], &result_len);
-         chopstx_setcancelstate (cs);
        }
       else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
        {
@@ -1047,11 +1043,9 @@ cmd_internal_authenticate (void)
          return;
        }
 
-      cs = chopstx_setcancelstate (0);
       result_len = pubkey_len;
       r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
                    &kd[GPG_KEY_FOR_AUTHENTICATION], pubkey_len);
-      chopstx_setcancelstate (cs);
     }
   else if (attr == ALGO_NISTP256R1)
     {