auth and keystring handling improvement (1)

This commit is contained in:
NIIBE Yutaka
2013-10-09 11:13:43 +09:00
parent 62e00a321e
commit b31e688536
5 changed files with 61 additions and 25 deletions

View File

@@ -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.

View File

@@ -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;
}

View 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);

View 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
{

View 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)
{
DEBUG_INFO ("done.\r\n");
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 */
{
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)