support PIN modification
authorNIIBE Yutaka <gniibe@fsij.org>
Mon, 17 Jan 2011 08:32:31 +0000 (17:32 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Mon, 17 Jan 2011 08:32:31 +0000 (17:32 +0900)
ChangeLog
src/gnuk.h
src/openpgp.c
src/pin-cir.c

index b0e192d..2142adb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2011-01-17  NIIBE Yutaka  <gniibe@fsij.org>
 
+       * src/gnuk.h (PIN_INPUT_CURRENT, PIN_INPUT_NEW)
+       (PIN_INPUT_CONFIRM): New.
+
+       * src/pin-cir.c (pin_main): New argument MSG_CODE.
+
+       * src/openpgp.c (get_pinpad_input): New.
+       (cmd_verify): Use get_pinpad_input.
+       (cmd_change_password): Added PINPAD_SUPPORT.
+
        * src/openpgp.c (cmd_nop): Removed.
 
        * src/config.h.in: ifdef-out (not for ASSEMBLER).
index 67cbf2f..ca4e5a2 100644 (file)
@@ -319,5 +319,8 @@ extern void cir_ext_enable (void);
 extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
 extern uint8_t pin_input_len;
 
+#define PIN_INPUT_CURRENT 1
+#define PIN_INPUT_NEW     2
+#define PIN_INPUT_CONFIRM 3
 extern msg_t pin_main (void *arg);
 #endif
index 1125aeb..bdc1c78 100644 (file)
@@ -94,6 +94,27 @@ gpg_fini (void)
   ac_fini ();
 }
 
+/* 
+ * Invoke the thread PIN_MAIN, and let user input PIN string.
+ * Return length of the string.
+ * The string itself is in PIN_INPUT_BUFFER.
+ */
+static int
+get_pinpad_input (int msg_code)
+{
+  Thread *t;
+
+  t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128),
+                          NORMALPRIO, pin_main, (void *)msg_code);
+  if (t == NULL)
+    return -1;
+  else
+    {
+      chThdWait (t);
+      return pin_input_len;
+    }
+}
+
 static void
 cmd_verify (void)
 {
@@ -108,23 +129,16 @@ cmd_verify (void)
 
 #if defined(PINPAD_SUPPORT)
   if (cmd_APDU_size == 4)
-    /* Verify with pinpad */
+    /* Verification with pinpad */
     {
-      Thread *t;
-
-      t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128),
-                              NORMALPRIO, pin_main, NULL);
-      if (t == NULL)
+      len = get_pinpad_input (PIN_INPUT_CURRENT);
+      if (len < 0)
        {
          GPG_ERROR ();
          return;
        }
       else
-       {
-         chThdWait (t);
-         pw = pin_input_buffer;
-         len = pin_input_len;
-       }
+       pw = pin_input_buffer;
     }
   else
 #endif
@@ -220,8 +234,8 @@ cmd_change_password (void)
   uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
   uint8_t *new_ks = &new_ks0[1];
   uint8_t p2 = cmd_APDU[3];
-  int len = cmd_APDU[4];
-  const uint8_t *pw = &cmd_APDU[5];
+  int len;
+  const uint8_t *pw;
   const uint8_t *newpw;
   int pw_len, newpw_len;
   int who = p2 - 0x80;
@@ -230,10 +244,55 @@ cmd_change_password (void)
   DEBUG_INFO ("Change PW\r\n");
   DEBUG_BYTE (who);
 
-  if (len == 0)                        /* extended length */
+#if defined(PINPAD_SUPPORT)
+  if (cmd_APDU_size == 4)
+    /* Modification with pinpad */
     {
-      len = (cmd_APDU[5]<<8) | cmd_APDU[6];
-      pw += 2;
+      pw_len = get_pinpad_input (PIN_INPUT_CURRENT);
+      if (pw_len < 0)
+       {
+         GPG_ERROR ();
+         return;
+       }
+
+      pw = &cmd_APDU[5];
+      memcpy (&cmd_APDU[5], pin_input_buffer, pw_len);
+      newpw = pw + pw_len;
+
+      newpw_len = get_pinpad_input (PIN_INPUT_NEW);
+      if (newpw_len < 0)
+       {
+         GPG_ERROR ();
+         return;
+       }
+
+      memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len);
+
+      len = get_pinpad_input (PIN_INPUT_CONFIRM);
+      if (len < 0)
+       {
+         GPG_ERROR ();
+         return;
+       }
+
+      if (len != newpw_len || memcmp (newpw, pin_input_buffer, len) != 0)
+       {
+         GPG_SECURITY_FAILURE ();
+         return;
+       }
+
+      len = cmd_APDU[4] = pw_len + newpw_len;
+    }
+  else
+#endif
+    {
+      len = cmd_APDU[4];
+      pw = &cmd_APDU[5];
+      if (len == 0)                    /* extended length */
+       {
+         len = (cmd_APDU[5]<<8) | cmd_APDU[6];
+         pw += 2;
+       }
     }
 
   if (who == BY_USER)                  /* PW1 */
index 86fe175..f8936a1 100644 (file)
@@ -240,8 +240,9 @@ msg_t
 pin_main (void *arg)
 {
   uint8_t s = 0;
+  int msg_code = (int)arg;
 
-  (void)arg;
+  (void)msg_code;
   pin_thread = chThdSelf ();
 
 #if defined(DEBUG_CIR)