Prevent observation of PW3 emptiness
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 10 May 2011 00:11:40 +0000 (09:11 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 10 May 2011 00:11:40 +0000 (09:11 +0900)
ChangeLog
src/ac.c
src/gnuk.h
src/openpgp-do.c
src/openpgp.c

index 06ac1af..046c88e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2011-05-10  NIIBE Yutaka  <gniibe@fsij.org>
+
+       Prevent observation of PW3 is emptiness by PW3's error counter.
+       Support verify_admin by PW1 when PW3 is empty.
+       * src/ac.c (admin_authorized): New.
+       (verify_admin_0): Set admin_authorized.
+       * src/openpgp-do.c (proc_resetting_code): Use admin_authorized.
+       (gpg_do_write_prvkey): Clear dek_encrypted_3 when keystring_admin
+       is NULL.
+       (proc_key_import): Checking admin_authorized, set keystring_admin.
+       * src/openpgp.c (cmd_reset_user_password): Use admin_authorized.
+
 2011-04-18  NIIBE Yutaka  <gniibe@fsij.org>
 
        * gnuk.svg: Updated.
index a1643d2..1562a73 100644 (file)
--- a/src/ac.c
+++ b/src/ac.c
@@ -161,6 +161,9 @@ calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
   memset (&sha1_ctx, 0, sizeof (sha1_ctx));
 }
 
+uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
+uint8_t admin_authorized;
+
 int
 verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
 {
@@ -191,25 +194,51 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
          gpg_increment_pw_err_counter (PW_ERR_PW3);
          return -1;
        }
-      else
-       /* OK, the user is now authenticated */
-       gpg_reset_pw_err_counter (PW_ERR_PW3);
+
+      admin_authorized = BY_ADMIN;
+    success:
+      /* OK, the user is now authenticated */
+      gpg_reset_pw_err_counter (PW_ERR_PW3);
+      return pw_len;
     }
   else
-    /* For empty PW3, pass phrase should be OPENPGP_CARD_INITIAL_PW3 */
     {
-      if ((pw_len_known >=0
-          && pw_len_known != strlen (OPENPGP_CARD_INITIAL_PW3))
-         || buf_len < (int)strlen (OPENPGP_CARD_INITIAL_PW3)
-         || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3,
-                     strlen (OPENPGP_CARD_INITIAL_PW3)) != 0)
-       /* It is failure, but we don't try to lock for the case of empty PW3 */
-       return -1;
-
-      pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
+      const uint8_t *ks_pw1;
+      uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
+
+      ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
+      if (ks_pw1 == NULL)
+       { /*
+          * For empty PW3 with empty PW1, pass phrase should be
+          * OPENPGP_CARD_INITIAL_PW3
+          */
+         if ((pw_len_known >=0
+              && pw_len_known != strlen (OPENPGP_CARD_INITIAL_PW3))
+             || buf_len < (int)strlen (OPENPGP_CARD_INITIAL_PW3)
+             || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3,
+                         strlen (OPENPGP_CARD_INITIAL_PW3)) != 0)
+           goto failure;
+
+         pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
+         admin_authorized = BY_ADMIN;
+         goto success;
+       }
+      else                     /* empty PW3, but PW1 exists */
+       {
+         pw_len = ks_pw1[0];
+         if (pw_len_known < 0 && pw_len_known != pw_len)
+           goto failure;
+
+         pw1_keystring[0] = pw_len;
+         sha1 (pw, pw_len, pw1_keystring+1);
+         if (gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER,
+                                 pw1_keystring + 1) < 0)
+           goto failure;
+
+         admin_authorized = BY_USER;
+         goto success; 
+       }
     }
-
-  return pw_len;
 }
 
 void
@@ -229,8 +258,6 @@ gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
   gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
 }
 
-uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
-
 int
 verify_admin (const uint8_t *pw, int pw_len)
 {
index 94adf10..fdf2681 100644 (file)
@@ -211,6 +211,7 @@ extern void fatal (uint8_t code) __attribute__ ((noreturn));
 #define FATAL_RANDOM 2
 
 extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
+extern uint8_t admin_authorized;
 
 /*** Flash memory tag values ***/
 #define NR_NONE                        0x00
index 0804382..161e92b 100644 (file)
@@ -525,7 +525,7 @@ proc_resetting_code (const uint8_t *data, int len)
   newpw = data;
   sha1 (newpw, newpw_len, new_ks);
   new_ks0[0] = newpw_len;
-  r = gpg_change_keystring (BY_ADMIN, old_ks, BY_RESETCODE, new_ks);
+  r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
   if (r < -2)
     {
       DEBUG_INFO ("memory error.\r\n");
@@ -656,7 +656,7 @@ static int8_t num_prv_keys;
 
 static int
 gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
-                    const uint8_t *keystring)
+                    const uint8_t *keystring_admin)
 {
   uint8_t nr = get_do_ptr_nr_for_kk (kk);
   const uint8_t *p;
@@ -752,7 +752,10 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
   else
     memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE);
 
-  encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
+  if (keystring_admin)
+    encrypt (keystring_admin, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
+  else
+    memset (pd->dek_encrypted_3, 0, DATA_ENCRYPTION_KEY_SIZE);
 
   p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
   do_ptr[nr - NR_DO__FIRST__] = p;
@@ -834,6 +837,13 @@ proc_key_import (const uint8_t *data, int len)
 {
   int r;
   enum kind_of_key kk;
+  const uint8_t *pw3_keystring;
+  const uint8_t *keystring_admin;
+
+  if (admin_authorized == BY_ADMIN)
+    keystring_admin = keystring_md_pw3;
+  else
+    keystring_admin = NULL;
 
   DEBUG_BINARY (data, len);
 
@@ -869,7 +879,7 @@ proc_key_import (const uint8_t *data, int len)
 
   /* It should starts with 00 01 00 01 (E) */
   /* Skip E, 4-byte */
-  r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_md_pw3);
+  r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin);
   if (r < 0)
     return 0;
   else
@@ -941,8 +951,8 @@ gpg_do_table[] = {
   { GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
     proc_key_import },
 #if 0
-  /* Card holder certificate */
-  { GPG_DO_CH_CERTIFICATE, DO_PROC_READ, AC_ALWAYS, AC_NEVER, NULL },
+  /* Card holder certificate is handled in special way, as its size is big */
+  { GPG_DO_CH_CERTIFICATE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
 #endif
 };
 
index 8758358..9bde988 100644 (file)
@@ -537,7 +537,7 @@ cmd_reset_user_password (void)
       newpw = pw;
       sha1 (newpw, newpw_len, new_ks);
       new_ks0[0] = newpw_len;
-      r = gpg_change_keystring (BY_ADMIN, old_ks, BY_USER, new_ks);
+      r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks);
       if (r < -2)
        {
          DEBUG_INFO ("memory error.\r\n");