Add UIF Data Object support for Acknowledge Button.
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 27 Sep 2018 06:02:43 +0000 (15:02 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 27 Sep 2018 06:02:43 +0000 (15:02 +0900)
ChangeLog
src/gnuk.h
src/openpgp-do.c
src/openpgp.c

index 87c6cb9..f220ea8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2018-09-27  NIIBE Yutaka  <gniibe@fsij.org>
+
+       * src/gnuk.h (NR_DO_UIF_SIG, NR_DO_UIF_DEC, NR_DO_UIF_AUT): New.
+       * src/openpgp-do.c (rw_uif) [ACKBTN_SUPPORT]: New.
+       (GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT): New.
+       (feature_mngmnt) [ACKBTN_SUPPORT]: New.
+       (cmp_app_data, cmp_discretionary): Add ACKBTN_SUPPORT.
+       (gpg_do_table): Add for GPG_DO_UIF_SIG, GPG_DO_UIF_DEC,
+       GPG_DO_UIF_AUT, and GPG_DO_FEATURE_MNGMNT.
+       (gpg_do_get_uif) [ACKBTN_SUPPORT]: New.
+       (gpg_data_scan): Handle uif_flags.
+       * src/openpgp.c (process_command_apdu) [ACKBTN_SUPPORT]: Add user
+       interaction handling.
+
 2018-09-27  NIIBE Yutaka  <gniibe@fsij.org>
 
        * src/gnuk.h (LED_WAIT_FOR_BUTTON): New.
index 2084026..4bdc2f9 100644 (file)
@@ -124,8 +124,8 @@ const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
 
 enum kind_of_key {
   GPG_KEY_FOR_SIGNING = 0,
-  GPG_KEY_FOR_DECRYPTION,
-  GPG_KEY_FOR_AUTHENTICATION,
+  GPG_KEY_FOR_DECRYPTION = 1,
+  GPG_KEY_FOR_AUTHENTICATION = 2,
 };
 
 enum size_of_key {
@@ -297,6 +297,7 @@ void gpg_increment_digital_signature_counter (void);
 void gpg_do_get_initial_pw_setting (int is_pw3, int *r_len,
                                    const uint8_t **r_p);
 int gpg_do_kdf_check (int len, int how_many);
+int gpg_do_get_uif (enum kind_of_key kk);
 
 
 void fatal (uint8_t code) __attribute__ ((noreturn));
@@ -380,9 +381,9 @@ extern uint8_t admin_authorized;
 #define NR_KEY_ALGO_ATTR_AUT   0xf3
 /*
  * Representation of User Interaction Flag:
- *  0 (UIF disabled):            No record in flash memory
- *  1 (UIF enabled):             0xf?ff
- *  2 (UIF permanently enabled): 0xf?00
+ *  0 (UIF disabled):            0xf?00 or No record in flash memory
+ *  1 (UIF enabled):             0xf?01
+ *  2 (UIF permanently enabled): 0xf?02
  *
  */
 #define NR_DO_UIF_SIG          0xf6
index c463aad..02d9a62 100644 (file)
@@ -135,11 +135,13 @@ static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
   0x01, 0x00,
 };
 
+#ifdef ACKBTN_SUPPORT
 /* General Feature Management */
 static const uint8_t feature_mngmnt[] __attribute__ ((aligned (1))) = {
   3,
   0x81, 0x01, 0x20,
 };
+#endif
 
 /* Algorithm Attributes */
 #define OPENPGP_ALGO_RSA   0x01
@@ -813,6 +815,64 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
     }
 }
 
+
+static uint8_t uif_flags;      /* Six bits of flags */
+
+#ifdef ACKBTN_SUPPORT
+int
+gpg_do_get_uif (enum kind_of_key kk)
+{
+  return ((uif_flags >> (kk * 2)) & 3) != 0;
+}
+
+static int
+rw_uif (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write)
+{
+  uint8_t nr;
+  int v;
+
+  if (tag != GPG_DO_UIF_SIG || tag != GPG_DO_UIF_DEC || tag != GPG_DO_UIF_AUT)
+    return 0;          /* Failure */
+
+  nr = (tag - GPG_DO_UIF_SIG) + NR_DO_UIF_SIG;
+  v = (uif_flags >> ((tag - GPG_DO_UIF_SIG) * 2)) & 3;
+  if (is_write)
+    {
+      const uint8_t *p;
+
+      if (len != 2 || data[1] != 0x20)
+       return 0;
+
+      if (v == 2)
+       return 0;
+
+      if (data[0] != 0x00 || data[0] != 0x01 || data[0] != 0x02)
+       return 0;
+
+      p = flash_enum_write (nr, data[0]);
+      if (p == NULL)
+       return 0;
+
+      uif_flags &= ~(3 << ((nr - NR_DO_UIF_SIG) * 2));
+      uif_flags |= (data[0] & 3) << ((nr - NR_DO_UIF_SIG) * 2);
+      return 1;
+    }
+  else
+    {
+      if (with_tag)
+       {
+         copy_tag (tag);
+         *res_p++ = 2;
+       }
+
+      *res_p++ = v;
+      *res_p++ = 0x20;
+      return 1;
+    }
+}
+#endif
+
+
 #define SIZE_OF_KDF_DO_MIN              90
 #define SIZE_OF_KDF_DO_MAX             110
 #define OPENPGP_KDF_ITERSALTED_S2K 3
@@ -1620,20 +1680,32 @@ static const uint16_t cmp_ch_data[] = {
 };
 
 static const uint16_t cmp_app_data[] = {
+#ifdef ACKBTN_SUPPORT
   4,
+#else
+  3,
+#endif
   GPG_DO_AID,
   GPG_DO_HIST_BYTES,
   GPG_DO_DISCRETIONARY,
+#ifdef ACKBTN_SUPPORT
   GPG_DO_FEATURE_MNGMNT,
+#endif
 };
 
 static const uint16_t cmp_discretionary[] = {
+#ifdef ACKBTN_SUPPORT
   11,
+#else
+  8,
+#endif
   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,
+#ifdef ACKBTN_SUPPORT
   GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT
+#endif
 };
 
 static const uint16_t cmp_ss_temp[] = { 1, GPG_DO_DS_COUNT };
@@ -1672,15 +1744,19 @@ gpg_do_table[] = {
     rw_algorithm_attr },
   { GPG_DO_ALG_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
     rw_algorithm_attr },
+#ifdef ACKBTN_SUPPORT
   { 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 },
+#endif
   { 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 },
+#ifdef ACKBTN_SUPPORT
   { GPG_DO_FEATURE_MNGMNT, DO_FIXED, AC_ALWAYS, AC_NEVER, feature_mngmnt },
+#endif
   /* 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 },
@@ -1719,6 +1795,7 @@ gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
   pw_err_counter_p[PW_ERR_PW3] = NULL;
   algo_attr_sig_p = algo_attr_dec_p = algo_attr_aut_p = NULL;
   digital_signature_counter = 0;
+  uif_flags = 0;
 
   /* When the card is terminated no data objects are valid.  */
   if (do_start == NULL)
@@ -1777,6 +1854,12 @@ gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
                algo_attr_aut_p = p - 1;
                p++;
                break;
+             case NR_DO_UIF_SIG:
+             case NR_DO_UIF_DEC:
+             case NR_DO_UIF_AUT:
+               uif_flags &= ~(3 << ((nr - NR_DO_UIF_SIG) * 2));
+               uif_flags |= (second_byte & 3) << ((nr - NR_DO_UIF_SIG) * 2);
+               break;
              case NR_COUNTER_123:
                p++;
                if (second_byte <= PW_ERR_PW3)
index 73cbc05..af17abe 100644 (file)
@@ -1506,6 +1506,9 @@ process_command_apdu (void)
 {
   int i;
   uint8_t cmd = INS (apdu);
+#ifdef ACKBTN_SUPPORT
+  uint8_t was_signing = (P1 (apdu) == 0x9e && P2 (apdu) == 0x9a);
+#endif
 
   for (i = 0; i < NUM_CMDS; i++)
     if (cmds[i].command == cmd)
@@ -1537,7 +1540,21 @@ process_command_apdu (void)
       GPG_NO_INS ();
     }
 
-  return (cmd == INS_PSO) | (cmd == INS_INTERNAL_AUTHENTICATE);
+#ifdef ACKBTN_SUPPORT
+  if (cmd == INS_PSO)
+    {
+      if (was_signing)
+       return gpg_do_get_uif (GPG_KEY_FOR_SIGNING);
+      else
+       return gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION);
+    }
+  else if (cmd == INS_INTERNAL_AUTHENTICATE)
+    return gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION);
+  else
+    return 0;
+#else
+  return 0;
+#endif
 }
 
 void *