Experimental Ack-button feature added (not yet finished).
authorNIIBE Yutaka <gniibe@fsij.org>
Wed, 26 Sep 2018 22:30:17 +0000 (07:30 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Wed, 26 Sep 2018 22:30:17 +0000 (07:30 +0900)
src/Makefile
src/ack-button.c [new file with mode: 0644]
src/gnuk.h
src/openpgp-do.c
src/openpgp.c
src/usb-ccid.c
src/usb_ctrl.c

index b864e60..f46738f 100644 (file)
@@ -51,6 +51,7 @@ endif
 
 ifeq ($(CHIP),stm32f103)
 CSRC += mcu-stm32f103.c 
+CSRC += ack-button.c
 endif
 
 ###################################
diff --git a/src/ack-button.c b/src/ack-button.c
new file mode 100644 (file)
index 0000000..6de8b7b
--- /dev/null
@@ -0,0 +1,35 @@
+#include <stdint.h>
+#include <string.h>
+#include <chopstx.h>
+
+#include "board.h"
+#include "mcu/stm32f103.h"
+
+void
+ackbtn_init (chopstx_intr_t *intr)
+{
+  chopstx_claim_irq (intr, INTR_REQ_EXTI);
+
+  /* Configure EXTI line */
+#ifdef AFIO_EXTICR_INDEX
+  AFIO->EXTICR[AFIO_EXTICR_INDEX] = AFIO_EXTICR1_EXTIx_Py;
+#endif
+  EXTI->IMR &= ~EXTI_IMR;
+  EXTI->RTSR |= EXTI_RTSR_TR;
+}
+
+void
+ackbtn_enable (void)
+{
+  EXTI->PR |= EXTI_PR;
+  EXTI->IMR |= EXTI_IMR;
+}
+
+void
+ackbtn_disable (void)
+{
+  EXTI->IMR &= ~EXTI_IMR;
+  EXTI->PR |= EXTI_PR;
+}
+
+
index e0e05cf..bca8af8 100644 (file)
@@ -24,10 +24,11 @@ extern struct apdu apdu;
 void ccid_card_change_signal (int how);
 
 /* CCID thread */
-#define EV_RX_DATA_READY   1 /* USB Rx data available  */
-#define EV_EXEC_FINISHED   2 /* OpenPGP Execution finished */
-#define EV_TX_FINISHED     4 /* CCID Tx finished  */
-#define EV_CARD_CHANGE     8
+#define EV_RX_DATA_READY      1 /* USB Rx data available  */
+#define EV_EXEC_FINISHED      2 /* OpenPGP Execution finished */
+#define EV_EXEC_FINISHED_ACK  4 /* OpenPGP Execution finished, requires ACK */
+#define EV_TX_FINISHED        8 /* CCID Tx finished  */
+#define EV_CARD_CHANGE       16
 
 /* OpenPGPcard thread */
 #define EV_PINPAD_INPUT_DONE      1
@@ -53,12 +54,12 @@ enum ccid_state {
   CCID_STATE_NOCARD,           /* No card available */
   CCID_STATE_START,            /* Initial */
   CCID_STATE_WAIT,             /* Waiting APDU */
-                               /* Busy1, Busy2, Busy3, Busy5 */
-  CCID_STATE_EXECUTE,          /* Busy4 */
+  CCID_STATE_EXECUTE,          /* Executing command */
+  CCID_STATE_CONFIRM_ACK,      /* Execution finished, waiting user's ACK */
   CCID_STATE_RECEIVE,          /* APDU Received Partially */
   CCID_STATE_SEND,             /* APDU Sent Partially */
 
-  CCID_STATE_EXITED,           /* ICC Thread Terminated */
+  CCID_STATE_EXITED,           /* CCID Thread Terminated */
   CCID_STATE_EXEC_REQUESTED,   /* Exec requested */
 };
 
@@ -378,7 +379,17 @@ extern uint8_t admin_authorized;
 #define NR_KEY_ALGO_ATTR_DEC   0xf2
 #define NR_KEY_ALGO_ATTR_AUT   0xf3
 /*
- * NR_UINT_SOMETHING could be here...  Use 0xf[456789abcd]
+ * Representation of User Interaction Flag:
+ *  0 (UIF disabled):            No record in flash memory
+ *  1 (UIF enabled):             0xf?ff
+ *  2 (UIF permanently enabled): 0xf?00
+ *
+ */
+#define NR_DO_UIF_SIG          0xf6
+#define NR_DO_UIF_DEC          0xf7
+#define NR_DO_UIF_AUT          0xf8
+/*
+ * NR_UINT_SOMETHING could be here...  Use 0xf[459abcd]
  */
 /* 123-counters: Recorded in flash memory by 2-halfword (4-byte).  */
 /*
@@ -461,6 +472,12 @@ int pinpad_getline (int msg_code, uint32_t timeout_usec);
 
 #endif
 
+struct chx_intr;
+void ackbtn_init (struct chx_intr *intr);
+void ackbtn_enable (void);
+void ackbtn_disable (void);
+
+
 extern uint8_t _regnual_start, __heap_end__[];
 
 uint8_t * sram_address (uint32_t offset);
index a7ac155..c463aad 100644 (file)
@@ -135,6 +135,12 @@ static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
   0x01, 0x00,
 };
 
+/* General Feature Management */
+static const uint8_t feature_mngmnt[] __attribute__ ((aligned (1))) = {
+  3,
+  0x81, 0x01, 0x20,
+};
+
 /* Algorithm Attributes */
 #define OPENPGP_ALGO_RSA   0x01
 #define OPENPGP_ALGO_ECDH  0x12
@@ -1614,18 +1620,20 @@ static const uint16_t cmp_ch_data[] = {
 };
 
 static const uint16_t cmp_app_data[] = {
-  3,
+  4,
   GPG_DO_AID,
   GPG_DO_HIST_BYTES,
   GPG_DO_DISCRETIONARY,
+  GPG_DO_FEATURE_MNGMNT,
 };
 
 static const uint16_t cmp_discretionary[] = {
-  8,
+  11,
   GPG_DO_EXTCAP,
   GPG_DO_ALG_SIG, GPG_DO_ALG_DEC, GPG_DO_ALG_AUT,
   GPG_DO_PW_STATUS,
-  GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL
+  GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL,
+  GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT
 };
 
 static const uint16_t cmp_ss_temp[] = { 1, GPG_DO_DS_COUNT };
@@ -1664,11 +1672,15 @@ gpg_do_table[] = {
     rw_algorithm_attr },
   { GPG_DO_ALG_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
     rw_algorithm_attr },
+  { GPG_DO_UIF_SIG, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif },
+  { GPG_DO_UIF_DEC, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif },
+  { GPG_DO_UIF_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif },
   { GPG_DO_KDF, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
     rw_kdf },
   /* Fixed data */
   { GPG_DO_HIST_BYTES, DO_FIXED, AC_ALWAYS, AC_NEVER, historical_bytes },
   { GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities },
+  { GPG_DO_FEATURE_MNGMNT, DO_FIXED, AC_ALWAYS, AC_NEVER, feature_mngmnt },
   /* Compound data: Read access only */
   { GPG_DO_CH_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ch_data },
   { GPG_DO_APP_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_app_data },
index 134a8d2..15c024c 100644 (file)
@@ -1501,7 +1501,7 @@ const struct command cmds[] = {
 };
 #define NUM_CMDS ((int)(sizeof (cmds) / sizeof (struct command)))
 
-static void
+static int
 process_command_apdu (void)
 {
   int i;
@@ -1536,6 +1536,8 @@ process_command_apdu (void)
       DEBUG_BYTE (cmd);
       GPG_NO_INS ();
     }
+
+  return (cmd == INS_PSO) | (cmd == INS_INTERNAL_AUTHENTICATE);
 }
 
 void *
@@ -1553,6 +1555,7 @@ openpgp_card_thread (void *arg)
       int len, pw_len, newpw_len;
 #endif
       eventmask_t m = eventflag_wait (openpgp_comm);
+      int r = 0;
 
       DEBUG_INFO ("GPG!: ");
 
@@ -1640,10 +1643,11 @@ openpgp_card_thread (void *arg)
        break;
 
       led_blink (LED_START_COMMAND);
-      process_command_apdu ();
-      led_blink (LED_FINISH_COMMAND);
+      r = process_command_apdu ();
+      if (!r)
+       led_blink (LED_FINISH_COMMAND);
     done:
-      eventflag_signal (ccid_comm, EV_EXEC_FINISHED);
+      eventflag_signal (ccid_comm, r? EV_EXEC_FINISHED_ACK : EV_EXEC_FINISHED);
     }
 
   gpg_fini ();
index 8fd3505..759a2e7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * usb-ccid.c -- USB CCID protocol handling
  *
- * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
+ * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
  *               Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
@@ -1076,7 +1076,9 @@ ccid_send_data_block (struct ccid *c)
 static void
 ccid_send_data_block_time_extension (struct ccid *c)
 {
-  ccid_send_data_block_internal (c, CCID_CMD_STATUS_TIMEEXT, 1);
+  ccid_send_data_block_internal (c, CCID_CMD_STATUS_TIMEEXT,
+                                (c->ccid_state == CCID_STATE_CONFIRM_ACK?
+                                 0xff : 1));
 }
 
 static void
@@ -1461,6 +1463,7 @@ ccid_handle_data (struct ccid *c)
        }
       break;
     case CCID_STATE_EXECUTE:
+    case CCID_STATE_CONFIRM_ACK:
       if (c->ccid_header.msg_type == CCID_POWER_OFF)
        next_state = ccid_power_off (c);
       else if (c->ccid_header.msg_type == CCID_SLOT_STATUS)
@@ -1489,6 +1492,7 @@ ccid_handle_timeout (struct ccid *c)
   switch (c->ccid_state)
     {
     case CCID_STATE_EXECUTE:
+    case CCID_STATE_CONFIRM_ACK:
       ccid_send_data_block_time_extension (c);
       break;
     default:
@@ -1561,7 +1565,8 @@ extern int usb_get_descriptor (struct usb_dev *dev);
 extern void random_init (void);
 extern void random_fini (void);
 
-static chopstx_intr_t interrupt;
+static chopstx_intr_t ack_intr;
+static chopstx_intr_t usb_intr;
 
 /*
  * Return 0 for normal USB event
@@ -1576,7 +1581,7 @@ usb_event_handle (struct usb_dev *dev)
 
   e = usb_lld_event_handler (dev);
   ep_num = USB_EVENT_ENDP (e);
-  chopstx_intr_done (&interrupt);
+  chopstx_intr_done (&usb_intr);
 
   /* Transfer to endpoint (not control endpoint) */
   if (ep_num != 0)
@@ -1678,7 +1683,8 @@ usb_event_handle (struct usb_dev *dev)
 
 static chopstx_poll_cond_t ccid_event_poll_desc;
 static struct chx_poll_head *const ccid_poll[] = {
-  (struct chx_poll_head *const)&interrupt,
+  (struct chx_poll_head *const)&ack_intr,
+  (struct chx_poll_head *const)&usb_intr,
   (struct chx_poll_head *const)&ccid_event_poll_desc
 };
 #define CCID_POLL_NUM (sizeof (ccid_poll)/sizeof (struct chx_poll_head *))
@@ -1697,9 +1703,10 @@ ccid_thread (void *arg)
   eventflag_init (&ccid.openpgp_comm);
 
   usb_lld_init (&dev, USB_INITIAL_FEATURE);
-  chopstx_claim_irq (&interrupt, INTR_REQ_USB);
+  chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
   usb_event_handle (&dev);     /* For old SYS < 3.0 */
 
+  ackbtn_init (&ack_intr);
   eventflag_prepare_poll (&c->ccid_comm, &ccid_event_poll_desc);
 
  reset:
@@ -1732,7 +1739,7 @@ ccid_thread (void *arg)
 
       chopstx_poll (timeout_p, CCID_POLL_NUM, ccid_poll);
 
-      if (interrupt.ready)
+      if (usb_intr.ready)
        {
          if (usb_event_handle (&dev) == 0)
            continue;
@@ -1752,6 +1759,15 @@ ccid_thread (void *arg)
          goto reset;
        }
 
+      if (ack_intr.ready)
+       {
+         ackbtn_disable ();
+         chopstx_intr_done (&ack_intr);
+         led_blink (LED_FINISH_COMMAND);
+         if (c->ccid_state == CCID_STATE_CONFIRM_ACK)
+           goto exec_done;
+       }
+
       timeout = USB_CCID_TIMEOUT;
       m = eventflag_get (&c->ccid_comm);
 
@@ -1779,6 +1795,7 @@ ccid_thread (void *arg)
       else if (m == EV_EXEC_FINISHED)
        if (c->ccid_state == CCID_STATE_EXECUTE)
          {
+         exec_done:
            if (c->a->sw == GPG_THREAD_TERMINATED)
              {
                c->sw1sw2[0] = 0x90;
@@ -1810,7 +1827,17 @@ ccid_thread (void *arg)
          }
        else
          {
-           DEBUG_INFO ("ERR07\r\n");
+           DEBUG_INFO ("ERR05\r\n");
+         }
+      else if (m == EV_EXEC_FINISHED_ACK)
+       if (c->ccid_state == CCID_STATE_EXECUTE)
+         {
+           ackbtn_enable ();
+           c->ccid_state = CCID_STATE_CONFIRM_ACK;
+         }
+       else
+         {
+           DEBUG_INFO ("ERR06\r\n");
          }
       else if (m == EV_TX_FINISHED)
        {
@@ -1842,7 +1869,7 @@ ccid_thread (void *arg)
   /* Loading reGNUal.  */
   while (bDeviceState != USB_DEVICE_STATE_UNCONNECTED)
     {
-      chopstx_intr_wait (&interrupt);
+      chopstx_intr_wait (&usb_intr);
       usb_event_handle (&dev);
     }
 
index 7b33ac9..c494b97 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * usb_ctrl.c - USB control pipe device specific code for Gnuk
  *
- * Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017
+ * Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018
  *               Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *