Version 0.10
[gnuk/gnuk.git] / src / ac.c
index b3acabb..a1643d2 100644 (file)
--- a/src/ac.c
+++ b/src/ac.c
@@ -28,7 +28,7 @@
 #include "polarssl/config.h"
 #include "polarssl/sha1.h"
 
-static uint8_t auth_status = AC_NONE_AUTHORIZED;
+uint8_t volatile auth_status = AC_NONE_AUTHORIZED;
 
 int
 ac_check_status (uint8_t ac_flag)
@@ -44,28 +44,28 @@ ac_check_status (uint8_t ac_flag)
 void
 ac_reset_pso_cds (void)
 {
+  gpg_do_clear_prvkey (GPG_KEY_FOR_SIGNING);
   auth_status &= ~AC_PSO_CDS_AUTHORIZED;
 }
 
-uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
-
 void
-ac_reset_pso_other (void)
+ac_reset_other (void)
 {
-  memset (pw1_keystring, 0, KEYSTRING_SIZE_PW1);
-  auth_status &= ~AC_PSO_OTHER_AUTHORIZED;
+  gpg_do_clear_prvkey (GPG_KEY_FOR_DECRYPTION);
+  gpg_do_clear_prvkey (GPG_KEY_FOR_AUTHENTICATION);
+  auth_status &= ~AC_OTHER_AUTHORIZED;
 }
 
+/*
+ * Verify for "Perform Security Operation : Compute Digital Signature"
+ */
 int
 verify_pso_cds (const uint8_t *pw, int pw_len)
 {
   int r;
-  const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
   uint8_t keystring[KEYSTRING_SIZE_PW1];
-  uint8_t pwsb[SIZE_PW_STATUS_BYTES];
 
-  if (pw_status_bytes == NULL
-      || pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
+  if (gpg_passwd_locked (PW_ERR_PW1))
     return 0;
 
   DEBUG_INFO ("verify_pso_cds\r\n");
@@ -73,59 +73,52 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
 
   keystring[0] = pw_len;
   sha1 (pw, pw_len, keystring+1);
-  memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
   if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring+1)) < 0)
     {
-      pwsb[PW_STATUS_PW1]--;
-      gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
+      gpg_increment_pw_err_counter (PW_ERR_PW1);
       return r;
     }
-  else if (pwsb[PW_STATUS_PW1] != 3)
-    {
-      pwsb[PW_STATUS_PW1] = 3;
-      gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
-    }
+  else
+    gpg_reset_pw_err_counter (PW_ERR_PW1);
 
   auth_status |= AC_PSO_CDS_AUTHORIZED;
   return 1;
 }
 
 int
-verify_pso_other (const uint8_t *pw, int pw_len)
+verify_other (const uint8_t *pw, int pw_len)
 {
-  const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
-  uint8_t pwsb[SIZE_PW_STATUS_BYTES];
   const uint8_t *ks_pw1;
+  uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
 
-  DEBUG_INFO ("verify_pso_other\r\n");
+  DEBUG_INFO ("verify_other\r\n");
 
-  if (pw_status_bytes == NULL
-      || pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
+  if (gpg_passwd_locked (PW_ERR_PW1))
     return 0;
 
-  memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
-
-  /*
-   * We check only the length of password string now.
-   * Real check is defered to decrypt/authenticate routines.
-   */
   ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
   if ((ks_pw1 == NULL && pw_len == strlen (OPENPGP_CARD_INITIAL_PW1))
       || (ks_pw1 != NULL && pw_len == ks_pw1[0]))
     {                          /* No problem */
-      /*
-       * We don't reset pwsb[PW_STATUS_PW1] here.
-       * Because password may be wrong.
-       */
       pw1_keystring[0] = pw_len;
       sha1 (pw, pw_len, pw1_keystring+1);
-      auth_status |= AC_PSO_OTHER_AUTHORIZED;
+      if (gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER,
+                             pw1_keystring + 1) < 0)
+       goto error;
+
+      if (gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER,
+                             pw1_keystring + 1) < 0)
+       goto error;
+
+      /* Reset counter as it's success now */
+      gpg_reset_pw_err_counter (PW_ERR_PW1);
+      auth_status |= AC_OTHER_AUTHORIZED;
       return 1;
     }
   else
     {
-      pwsb[PW_STATUS_PW1]--;
-      gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
+    error:
+      gpg_increment_pw_err_counter (PW_ERR_PW1);
       return 0;
     }
 }
@@ -172,11 +165,9 @@ int
 verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
 {
   const uint8_t *pw3_keystring;
-  const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
   int pw_len;
 
-  if (pw_status_bytes == NULL
-      || pw_status_bytes[PW_STATUS_PW3] == 0) /* locked */
+  if (gpg_passwd_locked (PW_ERR_PW3))
     return 0;
 
   pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
@@ -185,7 +176,6 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
       int count;
       uint8_t md[KEYSTRING_MD_SIZE];
       const uint8_t *salt;
-      uint8_t pwsb[SIZE_PW_STATUS_BYTES];
 
       pw_len = pw3_keystring[0];
       if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
@@ -194,32 +184,29 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
       salt = &pw3_keystring[1];
       count = decode_iterate_count (pw3_keystring[1+8]);
       calc_md (count, salt, pw, pw_len, md);
-      memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
 
       if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
        {
        failure:
-         pwsb[PW_STATUS_PW3]--;
-         gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
+         gpg_increment_pw_err_counter (PW_ERR_PW3);
          return -1;
        }
-      else if (pwsb[PW_STATUS_PW3] != 3)
-       {                      /* OK, the user is now authenticated */
-         pwsb[PW_STATUS_PW3] = 3;
-         gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
-       }
+      else
+       /* OK, the user is now authenticated */
+       gpg_reset_pw_err_counter (PW_ERR_PW3);
     }
   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))
+      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 = 8;
+      pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
     }
 
   return pw_len;
@@ -257,3 +244,19 @@ verify_admin (const uint8_t *pw, int pw_len)
   auth_status |= AC_ADMIN_AUTHORIZED;
   return 1;
 }
+
+void
+ac_reset_admin (void)
+{
+  memset (keystring_md_pw3, 0, KEYSTRING_MD_SIZE);
+  auth_status &= ~AC_ADMIN_AUTHORIZED;
+}
+
+void
+ac_fini (void)
+{
+  auth_status = AC_NONE_AUTHORIZED;
+  gpg_do_clear_prvkey (GPG_KEY_FOR_SIGNING);
+  gpg_do_clear_prvkey (GPG_KEY_FOR_DECRYPTION);
+  gpg_do_clear_prvkey (GPG_KEY_FOR_AUTHENTICATION);
+}