allow cancelling execution of commands which take long time
authorNIIBE Yutaka <gniibe@fsij.org>
Wed, 9 Sep 2015 10:12:50 +0000 (19:12 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Wed, 9 Sep 2015 10:14:19 +0000 (19:14 +0900)
ChangeLog
chopstx
src/main.c
src/openpgp-do.c
src/openpgp.c

index dc08598..788c300 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 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.
 
        * src/usb-icc.c (ccid_usb_reset): New.
diff --git a/chopstx b/chopstx
index baef99b..acd4460 160000 (submodule)
--- a/chopstx
+++ b/chopstx
@@ -1 +1 @@
-Subproject commit baef99bf11db42df18e2155e14fe774260747c91
+Subproject commit acd4460a6ee0f7caa1d7871acd51cdcf6bb4264c
index e598f41..b9d553a 100644 (file)
@@ -392,7 +392,7 @@ main (int argc, char *argv[])
          display_fatal_code ();
          break;
        case LED_USB_RESET:
-         ccid_reset ();
+         ccid_usb_reset ();
          chopstx_join (ccid_thd, NULL);
          /* Invoke the CCID thread again.  */
          ccid_thd = chopstx_create (PRIO_CCID, __stackaddr_ccid,
index e18f42d..78cb180 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <stdlib.h>
+#include <chopstx.h>
 
 #include "config.h"
 
@@ -2059,7 +2060,10 @@ 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 5964de7..c1e9693 100644 (file)
@@ -817,6 +817,7 @@ cmd_pso (void)
   int attr;
   int pubkey_len;
   unsigned int result_len = 0;
+  int cs;
 
   DEBUG_INFO (" - PSO: ");
   DEBUG_WORD ((uint32_t)&r);
@@ -853,9 +854,11 @@ 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)
        {
@@ -867,6 +870,7 @@ cmd_pso (void)
              return;
            }
 
+         cs = chopstx_setcancelstate (0);
          result_len = ECDSA_SIGNATURE_LENGTH;
          if (attr == ALGO_NISTP256R1)
            r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
@@ -874,6 +878,7 @@ cmd_pso (void)
          else                  /* ALGO_SECP256K1 */
            r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
                                   kd[GPG_KEY_FOR_SIGNING].data);
+         chopstx_setcancelstate (cs);
        }
       else if (attr == ALGO_ED25519)
        {
@@ -886,11 +891,13 @@ cmd_pso (void)
              return;
            }
 
+         cs = chopstx_setcancelstate (0);
          result_len = EDDSA_SIGNATURE_LENGTH;
          r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
                                kd[GPG_KEY_FOR_SIGNING].data,
                                kd[GPG_KEY_FOR_SIGNING].data+32,
                                kd[GPG_KEY_FOR_SIGNING].pubkey);
+         chopstx_setcancelstate (cs);
          memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
        }
       else
@@ -932,8 +939,10 @@ 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)
        {
@@ -947,6 +956,7 @@ cmd_pso (void)
              return;
            }
 
+         cs = chopstx_setcancelstate (0);
          result_len = 65;
          if (attr == ALGO_NISTP256R1)
            r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data + header, res_APDU,
@@ -954,6 +964,7 @@ cmd_pso (void)
          else
            r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data + header, res_APDU,
                                     kd[GPG_KEY_FOR_DECRYPTION].data);
+         chopstx_setcancelstate (cs);
        }
       else if (attr == ALGO_CURVE25519)
        {
@@ -965,9 +976,11 @@ cmd_pso (void)
              return;
            }
 
+         cs = chopstx_setcancelstate (0);
          result_len = 32;
          r = ecdh_decrypt_curve25519 (apdu.cmd_apdu_data + header, res_APDU,
                                       kd[GPG_KEY_FOR_DECRYPTION].data);
+         chopstx_setcancelstate (cs);
        }
       else
        {
@@ -1003,6 +1016,7 @@ cmd_internal_authenticate (void)
   int len = apdu.cmd_apdu_data_len;
   int r = -1;
   unsigned int result_len = 0;
+  int cs;
 
   DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
 
@@ -1033,9 +1047,11 @@ 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)
     {
@@ -1046,9 +1062,11 @@ cmd_internal_authenticate (void)
          return;
        }
 
+      cs = chopstx_setcancelstate (0);
       result_len = ECDSA_SIGNATURE_LENGTH;
       r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
                             kd[GPG_KEY_FOR_AUTHENTICATION].data);
+      chopstx_setcancelstate (cs);
     }
   else if (attr == ALGO_SECP256K1)
     {
@@ -1059,9 +1077,11 @@ cmd_internal_authenticate (void)
          return;
        }
 
+      cs = chopstx_setcancelstate (0);
       result_len = ECDSA_SIGNATURE_LENGTH;
       r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
                             kd[GPG_KEY_FOR_AUTHENTICATION].data);
+      chopstx_setcancelstate (cs);
     }
   else if (attr == ALGO_ED25519)
     {
@@ -1074,11 +1094,13 @@ cmd_internal_authenticate (void)
          return;
        }
 
+      cs = chopstx_setcancelstate (0);
       result_len = EDDSA_SIGNATURE_LENGTH;
       r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
                            kd[GPG_KEY_FOR_AUTHENTICATION].data,
                            kd[GPG_KEY_FOR_AUTHENTICATION].data+32,
                            kd[GPG_KEY_FOR_AUTHENTICATION].pubkey);
+      chopstx_setcancelstate (cs);
       memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
     }
 
@@ -1322,7 +1344,11 @@ process_command_apdu (void)
       break;
 
   if (i < NUM_CMDS)
-    cmds[i].cmd_handler ();
+    {
+      chopstx_setcancelstate (1);
+      cmds[i].cmd_handler ();
+      chopstx_setcancelstate (0);
+    }
   else
     {
       DEBUG_INFO (" - ??");
@@ -1355,10 +1381,10 @@ card_thread (chopstx_t thd, struct eventflag *ccid_comm)
 
   while (1)
     {
-      eventmask_t m = eventflag_wait (openpgp_comm);
 #if defined(PINPAD_SUPPORT)
       int len, pw_len, newpw_len;
 #endif
+      eventmask_t m = eventflag_wait (openpgp_comm);
 
       DEBUG_INFO ("GPG!: ");