Implement use of KDF data object.
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 2 Nov 2017 01:59:17 +0000 (10:59 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 2 Nov 2017 01:59:17 +0000 (10:59 +0900)
ChangeLog
src/ac.c
src/gnuk.h
src/openpgp-do.c
src/openpgp.c

index 859216c..673a76e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,12 @@
 2017-11-02  NIIBE Yutaka  <gniibe@fsij.org>
 
        * src/openpgp-do.c (rw_kdf): Only writable when no keys.
+       (gpg_do_get_initial_pw_setting): New.
+       (gpg_do_write_prvkey): Use gpg_do_get_initial_pw_setting.
+       (gpg_do_keygen): Likewise.
+       * src/openpgp.c (cmd_change_password): Use
+       gpg_do_get_initial_pw_setting.
+       * src/ac.c (verify_user_0, verify_admin_0): Likewise.
 
 2017-11-01  NIIBE Yutaka  <gniibe@fsij.org>
 
index f5c2fb3..21bf244 100644 (file)
--- a/src/ac.c
+++ b/src/ac.c
@@ -1,7 +1,7 @@
 /*
  * ac.c -- Check access condition
  *
- * Copyright (C) 2010, 2012, 2013 Free Software Initiative of Japan
+ * Copyright (C) 2010, 2012, 2013, 2017 Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -73,12 +73,14 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
 
   if (ks_pw1 == NULL)
     {
-      pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
+      const uint8_t *initial_pw;
+
       salt = NULL;
       salt_len = 0;
+      gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
       if ((pw_len_known >= 0 && pw_len_known != pw_len)
          || buf_len < pw_len
-         || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
+         || memcmp (pw, initial_pw, pw_len))
        goto failure;
     }
   else
@@ -220,6 +222,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
     }
   else
     {
+      const uint8_t *initial_pw;
       const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
 
       if (ks_pw1 != NULL)
@@ -237,13 +240,13 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
        return 0;
 
       /*
-       * For the case of empty PW3 (with empty PW1), pass phrase
-       * should be OPENPGP_CARD_INITIAL_PW3
+       * For the case of empty PW3 (with empty PW1), passphrase is
+       * OPENPGP_CARD_INITIAL_PW3, or defined by KDF DO.
        */
-      pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
+      gpg_do_get_initial_pw_setting (1, &pw_len, &initial_pw);
       if ((pw_len_known >=0 && pw_len_known != pw_len)
          || buf_len < pw_len
-         || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3, pw_len))
+         || memcmp (pw, initial_pw, pw_len))
        goto failure;
 
       admin_authorized = BY_ADMIN;
index 91cbf40..b10d538 100644 (file)
@@ -296,7 +296,8 @@ int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
 const uint8_t *gpg_do_read_simple (uint8_t);
 void gpg_do_write_simple (uint8_t, const uint8_t *, int);
 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);
 
 void fatal (uint8_t code) __attribute__ ((noreturn));
 #define FATAL_FLASH  1
index c886aa8..b78be72 100644 (file)
@@ -863,6 +863,34 @@ rw_kdf (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write)
     }
 }
 
+void
+gpg_do_get_initial_pw_setting (int is_pw3, int *r_len, const uint8_t **r_p)
+{
+  const uint8_t *kdf_spec = gpg_do_read_simple (NR_DO_KDF);
+
+  if (kdf_spec)
+    {
+      *r_len = 32;
+      if (is_pw3)
+       *r_p = kdf_spec + 78;
+      else
+       *r_p = kdf_spec + 44;
+    }
+  else
+    {
+      if (is_pw3)
+       {
+         *r_len = strlen (OPENPGP_CARD_INITIAL_PW3);
+         *r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW3;
+       }
+      else
+       {
+         *r_len = strlen (OPENPGP_CARD_INITIAL_PW1);
+         *r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
+       }
+    }
+}
+
 static int
 proc_resetting_code (const uint8_t *data, int len)
 {
@@ -1155,6 +1183,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
   int pubkey_len;
   uint8_t ks[KEYSTRING_MD_SIZE];
   enum kind_of_key kk0;
+  int pw_len;
+  const uint8_t *initial_pw;
 
   DEBUG_INFO ("Key import\r\n");
   DEBUG_SHORT (prvkey_len);
@@ -1212,8 +1242,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
   memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
   memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
 
-  s2k (NULL, 0, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1,
-       strlen (OPENPGP_CARD_INITIAL_PW1), ks);
+  gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
+  s2k (NULL, 0, initial_pw, pw_len, ks);
 
   /* Handle existing keys and keystring DOs.  */
   gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
@@ -2240,14 +2270,16 @@ gpg_do_keygen (uint8_t *buf)
 
   if (kk == GPG_KEY_FOR_SIGNING)
     {
-      const uint8_t *pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
+      int pw_len;
+      const uint8_t *initial_pw;
       uint8_t keystring[KEYSTRING_MD_SIZE];
 
       /* GnuPG expects it's ready for signing. */
       /* Don't call ac_reset_pso_cds here, but load the private key */
 
       gpg_reset_digital_signature_counter ();
-      s2k (NULL, 0, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring);
+      gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
+      s2k (NULL, 0, initial_pw, pw_len, keystring);
       gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
     }
   else
index f0d8d7b..a26e05e 100644 (file)
@@ -378,8 +378,10 @@ cmd_change_password (void)
          newpw_len = len - pw_len;
          if (newpw_len == 0 && admin_authorized == BY_ADMIN)
            {
-             newpw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
-             memcpy (newpw, OPENPGP_CARD_INITIAL_PW3, newpw_len);
+             const uint8_t *initial_pw;
+
+             gpg_do_get_initial_pw_setting (1, &newpw_len, &initial_pw);
+             memcpy (newpw, initial_pw, newpw_len);
              newsalt_len = 0;
              pw3_null = 1;
            }