auth and keystring handling improvement (1)
authorNIIBE Yutaka <gniibe@fsij.org>
Wed, 9 Oct 2013 02:13:43 +0000 (11:13 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Wed, 9 Oct 2013 02:13:43 +0000 (11:13 +0900)
ChangeLog
src/ac.c
src/gnuk.h
src/openpgp-do.c
src/openpgp.c

index 66ded49..1b5bd12 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-10-09  Niibe Yutaka  <gniibe@fsij.org>
+
+       * src/ac.c (verify_admin_00): New.  Add authentication by loading
+       signature key.
+       (verify_admin_0): Use verify_admin_00.
+
+       * src/openpgp.c (cmd_change_password): Admin keystring handling as
+       same as user's.
+
 2013-10-08  Niibe Yutaka  <gniibe@fsij.org>
 
        * src/openpgp.c (modify_binary): Allow odd size of certificate.
index fc40ac5..8aaea8c 100644 (file)
--- a/src/ac.c
+++ b/src/ac.c
@@ -1,7 +1,7 @@
 /*
  * ac.c -- Check access condition
  *
- * Copyright (C) 2010, 2012 Free Software Initiative of Japan
+ * Copyright (C) 2010, 2012, 2013 Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -186,6 +186,32 @@ calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
   sha256_finish (&sha256_ctx, md);
 }
 
+
+static int
+verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known,
+                const uint8_t *ks)
+{
+  int pw_len;
+  int r1, r2;
+  uint8_t keystring[KEYSTRING_MD_SIZE];
+
+  pw_len = ks[0];
+  if ((pw_len_known >= 0 && pw_len_known != pw_len) || buf_len < pw_len)
+    return -1;
+
+  s2k (BY_ADMIN, pw, pw_len, keystring);
+  r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_ADMIN, keystring);
+  r2 = 0;
+
+  if (r1 < 0 || r2 < 0)
+    return -1;
+  else if (r1 == 0 && r2 == 0)
+    if (ks != NULL && memcmp (ks+1, keystring, KEYSTRING_MD_SIZE) != 0)
+      return -1;
+
+  return pw_len;
+}
+
 uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
 uint8_t admin_authorized;
 
@@ -198,22 +224,11 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
   pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
   if (pw3_keystring != NULL)
     {
-      int count;
-      uint8_t md[KEYSTRING_MD_SIZE];
-      const uint8_t *salt;
-
       if (gpg_pw_locked (PW_ERR_PW3))
        return 0;
 
-      pw_len = pw3_keystring[0];
-      if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len > buf_len)
-       goto failure;
-
-      salt = &pw3_keystring[1];
-      count = decode_iterate_count (pw3_keystring[1+8]);
-      calc_md (count, salt, pw, pw_len, md);
-
-      if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
+      pw_len = verify_admin_00 (pw, buf_len, pw_len_known, pw3_keystring);
+      if (pw_len < 0)
        {
        failure:
          gpg_pw_increment_err_counter (PW_ERR_PW3);
@@ -221,7 +236,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
        }
 
       admin_authorized = BY_ADMIN;
-    success:                  /* OK, the user is now authenticated */
+    success:                  /* OK, the admin is now authenticated.  */
       gpg_pw_reset_err_counter (PW_ERR_PW3);
       return pw_len;
     }
index 9336b82..544fe47 100644 (file)
@@ -181,6 +181,7 @@ extern void s2k (int who, const unsigned char *input, unsigned int ilen,
 #define KEYSTRING_SIZE_RC  (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
 #define KEYSTRING_SIZE_PW3 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE \
                                +KEYSTRING_ITER_SIZE+KEYSTRING_MD_SIZE)
+#define KEYSTRING_SIZE     (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
 
 extern void gpg_do_clear_prvkey (enum kind_of_key kk);
 extern int gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring);
index 57b6909..e6f0a4a 100644 (file)
@@ -578,7 +578,7 @@ proc_resetting_code (const uint8_t *data, int len)
   else if (r == 0)
     {
       DEBUG_INFO ("done (no prvkey).\r\n");
-      gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KEYSTRING_SIZE_RC);
+      gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KEYSTRING_SIZE);
     }
   else
     {
index f745a53..5f5f938 100644 (file)
@@ -255,6 +255,7 @@ cmd_change_password (void)
   int who = p2 - 0x80;
   int who_old;
   int r;
+  int pw3_null = 0;
 
   DEBUG_INFO ("Change PW\r\n");
   DEBUG_BYTE (who);
@@ -328,9 +329,9 @@ cmd_change_password (void)
              newpw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
              memcpy (newpw, OPENPGP_CARD_INITIAL_PW3, newpw_len);
              gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0);
+             pw3_null = 1;
            }
-         else
-           gpg_set_pw3 (newpw, newpw_len);
+
          who_old = admin_authorized;
        }
     }
@@ -352,7 +353,7 @@ cmd_change_password (void)
     }
   else if (r == 0 && who == BY_USER)   /* no prvkey */
     {
-      gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
+      gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE);
       ac_reset_pso_cds ();
       ac_reset_other ();
       if (admin_authorized == BY_USER)
@@ -370,9 +371,21 @@ cmd_change_password (void)
       DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
       GPG_SUCCESS ();
     }
-  else                         /* r >= 0 && who == BY_ADMIN */
+#if 0
+  else if (r > 0 && who == BY_ADMIN)
+    {
+      if (!pw3_null)
+       gpg_do_write_simple (NR_DO_KEYSTRING_PW3, new_ks0, 1);
+      ac_reset_admin ();
+      DEBUG_INFO ("Changed length of DO_KEYSTRING_PW3.\r\n");
+      GPG_SUCCESS ();
+    }
+#endif
+  else /* r == 0 && who == BY_ADMIN */ /* no prvkey */
     {
-      DEBUG_INFO ("done.\r\n");
+      if (!pw3_null)
+       gpg_do_write_simple (NR_DO_KEYSTRING_PW3, new_ks0, KEYSTRING_SIZE);
+      DEBUG_INFO ("Changed DO_KEYSTRING_PW3.\r\n");
       ac_reset_admin ();
       GPG_SUCCESS ();
     }
@@ -462,8 +475,7 @@ cmd_reset_user_password (void)
          if (memcmp (ks_rc+1, old_ks, KEYSTRING_MD_SIZE) != 0)
            goto sec_fail;
          DEBUG_INFO ("done (no prvkey).\r\n");
-         gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0,
-                              KEYSTRING_SIZE_PW1);
+         gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE);
          ac_reset_pso_cds ();
          ac_reset_other ();
          if (admin_authorized == BY_USER)
@@ -514,8 +526,7 @@ cmd_reset_user_password (void)
       else if (r == 0)
        {
          DEBUG_INFO ("done (no privkey).\r\n");
-         gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0,
-                              KEYSTRING_SIZE_PW1);
+         gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE);
          ac_reset_pso_cds ();
          ac_reset_other ();
          if (admin_authorized == BY_USER)