Add SALT for pass phrase handling

This commit is contained in:
NIIBE Yutaka
2013-10-09 17:21:37 +09:00
parent 7f93ea088f
commit 6ad6b1d73a
7 changed files with 199 additions and 150 deletions

View File

@@ -1,3 +1,15 @@
2013-10-09 Niibe Yutaka <gniibe@fsij.org>
* src/ac.c (verify_user_0, verify_admin_00, verify_admin_0): Add a
flag to save into keystring_md_pw3. Add SALT handling.
(decode_iterate_count, calc_md, gpg_set_pw3): Remove.
* src/openpgp-do.c (proc_resetting_code, gpg_do_write_prvkey)
(gpg_do_keygen): Add SALT handling.
* src/openpgp.c (cmd_change_password, cmd_reset_user_password)
(s2k): Ditto.
* src/random.c (random_get_salt): Rename from get_salt.
2013-10-09 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_do_write_prvkey): Remove information (but

125
src/ac.c
View File

@@ -60,11 +60,13 @@ ac_reset_other (void)
int
verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
const uint8_t *ks_pw1)
const uint8_t *ks_pw1, int save_ks)
{
int pw_len;
int r1, r2;
uint8_t keystring[KEYSTRING_MD_SIZE];
const uint8_t *salt;
int salt_len;
if (gpg_pw_locked (PW_ERR_PW1))
return 0;
@@ -72,26 +74,28 @@ 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);
salt = NULL;
salt_len = 0;
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|| buf_len < pw_len
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
goto failure;
else
goto success_one_step;
}
else
pw_len = ks_pw1[0] & PW_LEN_MASK;
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|| buf_len < pw_len)
{
failure:
gpg_pw_increment_err_counter (PW_ERR_PW1);
return -1;
pw_len = ks_pw1[0] & PW_LEN_MASK;
salt = KS_GET_SALT (ks_pw1);
salt_len = SALT_SIZE;
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|| buf_len < pw_len)
goto failure;
}
success_one_step:
s2k (BY_USER, pw, pw_len, keystring);
s2k (salt, salt_len, pw, pw_len, keystring);
if (save_ks)
memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE);
if (access == AC_PSO_CDS_AUTHORIZED)
{
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
@@ -103,14 +107,15 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
r2 = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER, keystring);
}
if (r1 < 0 || r2 < 0)
if (r1 < 0 || r2 < 0
|| (r1 == 0 && r2 == 0 && ks_pw1 != NULL
&& memcmp (KS_GET_KEYSTRING (ks_pw1),
keystring, KEYSTRING_MD_SIZE) != 0))
{
failure:
gpg_pw_increment_err_counter (PW_ERR_PW1);
return -1;
}
else if (r1 == 0 && r2 == 0)
if (ks_pw1 != NULL && memcmp (ks_pw1+1, keystring, KEYSTRING_MD_SIZE) != 0)
goto failure;
gpg_pw_reset_err_counter (PW_ERR_PW1);
return pw_len;
@@ -128,7 +133,7 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
DEBUG_INFO ("verify_pso_cds\r\n");
DEBUG_BYTE (pw_len);
r = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, pw_len, pw_len, ks_pw1);
r = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, pw_len, pw_len, ks_pw1, 0);
if (r > 0)
auth_status |= AC_PSO_CDS_AUTHORIZED;
return r;
@@ -143,70 +148,41 @@ verify_other (const uint8_t *pw, int pw_len)
DEBUG_INFO ("verify_other\r\n");
DEBUG_BYTE (pw_len);
r = verify_user_0 (AC_OTHER_AUTHORIZED, pw, pw_len, pw_len, ks_pw1);
r = verify_user_0 (AC_OTHER_AUTHORIZED, pw, pw_len, pw_len, ks_pw1, 0);
if (r > 0)
auth_status |= AC_OTHER_AUTHORIZED;
return r;
}
/*
* For keystring of PW3, we use SALT+ITER+MD format
*/
static uint32_t
decode_iterate_count (uint8_t x)
{
return (16UL + ((x) & 15)) << (((x) >> 4) + 6);
}
static void
calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
uint8_t md[KEYSTRING_MD_SIZE])
{
sha256_context sha256_ctx;
sha256_start (&sha256_ctx);
while (count > pw_len + 8)
{
sha256_update (&sha256_ctx, salt, 8);
sha256_update (&sha256_ctx, pw, pw_len);
count -= pw_len + 8;
}
if (count <= 8)
sha256_update (&sha256_ctx, salt, count);
else
{
sha256_update (&sha256_ctx, salt, 8);
count -= 8;
sha256_update (&sha256_ctx, pw, count);
}
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)
const uint8_t *ks, int save_ks)
{
int pw_len;
int r1, r2;
uint8_t keystring[KEYSTRING_MD_SIZE];
const uint8_t *salt;
int salt_len;
pw_len = ks[0] & PW_LEN_MASK;
salt = KS_GET_SALT (ks);
salt_len = SALT_SIZE;
if ((pw_len_known >= 0 && pw_len_known != pw_len) || buf_len < pw_len)
return -1;
s2k (BY_ADMIN, pw, pw_len, keystring);
s2k (salt, salt_len, pw, pw_len, keystring);
if (save_ks)
memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE);
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)
if (memcmp (KS_GET_KEYSTRING (ks), keystring, KEYSTRING_MD_SIZE) != 0)
return -1;
return pw_len;
@@ -216,18 +192,18 @@ 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)
verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
const uint8_t *pw3_keystring, int save_ks)
{
const uint8_t *pw3_keystring;
int pw_len;
pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
if (pw3_keystring != NULL)
{
if (gpg_pw_locked (PW_ERR_PW3))
return 0;
pw_len = verify_admin_00 (pw, buf_len, pw_len_known, pw3_keystring);
pw_len = verify_admin_00 (pw, buf_len, pw_len_known, pw3_keystring,
save_ks);
if (pw_len < 0)
{
failure:
@@ -247,7 +223,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
if (ks_pw1 != NULL)
{ /* empty PW3, but PW1 exists */
int r = verify_user_0 (AC_PSO_CDS_AUTHORIZED,
pw, buf_len, pw_len_known, ks_pw1);
pw, buf_len, pw_len_known, ks_pw1, save_ks);
if (r > 0)
admin_authorized = BY_USER;
@@ -269,37 +245,24 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
goto failure;
admin_authorized = BY_ADMIN;
if (save_ks)
s2k (NULL, 0, pw, pw_len, keystring_md_pw3);
goto success;
}
}
void
gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
{
uint8_t ks[KEYSTRING_SIZE_PW3];
uint32_t random;
ks[0] = newpw_len;
random = get_salt ();
memcpy (&ks[1], &random, sizeof (random));
random = get_salt ();
memcpy (&ks[5], &random, sizeof (random));
ks[9] = 0x60; /* 65536 iterations */
calc_md (65536, &ks[1], newpw, newpw_len, &ks[10]);
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
}
int
verify_admin (const uint8_t *pw, int pw_len)
{
int r;
const uint8_t *pw3_keystring;
r = verify_admin_0 (pw, pw_len, pw_len);
pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
r = verify_admin_0 (pw, pw_len, pw_len, pw3_keystring, 1);
if (r <= 0)
return r;
s2k (admin_authorized, pw, pw_len, keystring_md_pw3);
auth_status |= AC_ADMIN_AUTHORIZED;
return 1;
}

View File

@@ -75,9 +75,10 @@ extern int ac_check_status (uint8_t ac_flag);
extern int verify_pso_cds (const uint8_t *pw, int pw_len);
extern int verify_other (const uint8_t *pw, int pw_len);
extern int verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len,
int pw_len_known, const uint8_t *ks_pw1);
int pw_len_known, const uint8_t *ks_pw1, int saveks);
extern int verify_admin (const uint8_t *pw, int pw_len);
extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known);
extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
const uint8_t *ks_pw3, int saveks);
extern void ac_reset_pso_cds (void);
extern void ac_reset_other (void);
@@ -177,19 +178,26 @@ struct prvkey_data {
#define PW_LEN_MASK 0x7f
#define PW_LEN_KEYSTRING_BIT 0x80
extern void s2k (int who, const unsigned char *input, unsigned int ilen,
unsigned char output[32]);
#define SALT_SIZE 8
void s2k (const unsigned char *salt, size_t slen,
const unsigned char *input, size_t ilen, unsigned char output[32]);
#define S2K_ITER 0x60 /* 65535 */
#define KEYSTRING_PASSLEN_SIZE 1
#define KEYSTRING_SALT_SIZE 8 /* optional */
#define KEYSTRING_ITER_SIZE 1 /* optional */
#define KEYSTRING_SALT_SIZE SALT_SIZE
#define KEYSTRING_ITER_SIZE 1
#define KEYSTRING_MD_SIZE 32
#define KEYSTRING_SIZE_PW1 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
#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)
#define KEYSTRING_SIZE (KEYSTRING_PASSLEN_SIZE + KEYSTRING_SALT_SIZE \
+ KEYSTRING_ITER_SIZE + KEYSTRING_MD_SIZE)
#define KS_META_SIZE (KEYSTRING_PASSLEN_SIZE + KEYSTRING_SALT_SIZE \
+ KEYSTRING_ITER_SIZE)
#define KS_GET_SALT(ks) (ks + KEYSTRING_PASSLEN_SIZE)
#define KS_GET_ITER(ks) (ks + KEYSTRING_PASSLEN_SIZE \
+ KEYSTRING_SALT_SIZE)
#define KS_GET_KEYSTRING(ks) (ks + KEYSTRING_PASSLEN_SIZE \
+ KEYSTRING_SALT_SIZE + KEYSTRING_ITER_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);
@@ -244,7 +252,6 @@ extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
extern void gpg_increment_digital_signature_counter (void);
extern void gpg_set_pw3 (const uint8_t *newpw, int newpw_len);
extern void fatal (uint8_t code) __attribute__ ((noreturn));
#define FATAL_FLASH 1
#define FATAL_RANDOM 2
@@ -328,8 +335,6 @@ extern uint8_t admin_authorized;
#define NUM_ALL_PRV_KEYS 3 /* SIG, DEC and AUT */
extern uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
#if !defined(OPENPGP_CARD_INITIAL_PW1)
#define OPENPGP_CARD_INITIAL_PW1 "123456"
#endif

View File

@@ -551,18 +551,21 @@ static int
proc_resetting_code (const uint8_t *data, int len)
{
const uint8_t *old_ks = keystring_md_pw3;
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
uint8_t *new_ks = &new_ks0[1];
uint8_t new_ks0[KEYSTRING_SIZE];
uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0);
const uint8_t *newpw;
int newpw_len;
int r;
uint8_t *salt = KS_GET_SALT (new_ks0);
DEBUG_INFO ("Resetting Code!\r\n");
newpw_len = len;
newpw = data;
s2k (BY_RESETCODE, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
random_get_salt (salt);
new_ks0[KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE] = S2K_ITER;
s2k (salt, SALT_SIZE, newpw, newpw_len, new_ks);
r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
if (r <= -2)
{
@@ -583,7 +586,7 @@ proc_resetting_code (const uint8_t *data, int len)
else
{
DEBUG_INFO ("done.\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, 1);
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KS_META_SIZE);
}
gpg_pw_reset_err_counter (PW_ERR_RC);
@@ -852,13 +855,13 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
if (ks_pw1)
{
ks_pw1_len = ks_pw1[0];
encrypt_dek (ks_pw1+1, pd->dek_encrypted_1);
encrypt_dek (KS_GET_KEYSTRING (ks_pw1), pd->dek_encrypted_1);
}
else
{
uint8_t ks[KEYSTRING_MD_SIZE];
s2k (BY_USER, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1,
s2k (NULL, 0, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1,
strlen (OPENPGP_CARD_INITIAL_PW1), ks);
encrypt_dek (ks, pd->dek_encrypted_1);
}
@@ -866,7 +869,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
if (ks_rc)
{
ks_rc_len = ks_rc[0];
encrypt_dek (ks_rc+1, pd->dek_encrypted_2);
encrypt_dek (KS_GET_KEYSTRING (ks_rc), pd->dek_encrypted_2);
}
else
memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE);
@@ -887,28 +890,37 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
if (++num_prv_keys == NUM_ALL_PRV_KEYS) /* All keys are registered. */
{
/* Remove contents of keystrings from DO, but length */
uint8_t ks_info[KS_META_SIZE];
/* Remove contents of keystrings from DO, but length, salt, and iter. */
if ((ks_pw1_len & PW_LEN_KEYSTRING_BIT))
{
ks_pw1_len &= PW_LEN_MASK;
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, &ks_pw1_len, 1);
ks_info[0] = ks_pw1_len;
memcpy (KS_GET_SALT (ks_info), KS_GET_SALT (ks_pw1), SALT_SIZE);
ks_info[KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE] = S2K_ITER;
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, ks_info, KS_META_SIZE);
}
if ((ks_rc_len & PW_LEN_KEYSTRING_BIT))
{
ks_rc_len &= PW_LEN_MASK;
gpg_do_write_simple (NR_DO_KEYSTRING_RC, &ks_rc_len, 1);
ks_info[0] = ks_rc_len;
memcpy (KS_GET_SALT (ks_info), KS_GET_SALT (ks_rc), SALT_SIZE);
ks_info[KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE] = S2K_ITER;
gpg_do_write_simple (NR_DO_KEYSTRING_RC, ks_info, KS_META_SIZE);
}
if (keystring_admin)
{
const uint8_t *ks_admin = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
uint8_t admin_pw_len;
if (ks_admin != NULL)
{
admin_pw_len = ks_admin[0] & PW_LEN_MASK;
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, &admin_pw_len, 1);
ks_info[0] = ks_admin[0] & PW_LEN_MASK;
memcpy (KS_GET_SALT (ks_info), KS_GET_SALT (ks_admin), SALT_SIZE);
ks_info[KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE] = S2K_ITER;
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks_info, KS_META_SIZE);
}
else
{
@@ -1044,10 +1056,13 @@ proc_key_import (const uint8_t *data, int len)
if (ks_pw3 != NULL)
{
uint8_t ks0[KEYSTRING_MD_SIZE+1];
uint8_t ks0[KEYSTRING_SIZE];
ks0[0] = ks_pw3[0] | PW_LEN_KEYSTRING_BIT;
memcpy (&ks0[1], keystring_md_pw3, KEYSTRING_MD_SIZE);
memcpy (KS_GET_SALT (ks0), KS_GET_SALT (ks_pw3), SALT_SIZE);
ks0[KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE] = S2K_ITER;
memcpy (KS_GET_KEYSTRING (ks0),
keystring_md_pw3, KEYSTRING_MD_SIZE);
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks0, KEYSTRING_SIZE);
}
}
@@ -1729,12 +1744,12 @@ gpg_do_keygen (uint8_t kk_byte)
/* Don't call ac_reset_pso_cds here, but load the private key */
if (ks_pw1)
ks = ks_pw1+1;
ks = KS_GET_KEYSTRING (ks_pw1);
else
{
const uint8_t * pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
s2k (BY_USER, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring);
s2k (NULL, 0, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring);
ks = keystring;
}

View File

@@ -245,8 +245,10 @@ static void
cmd_change_password (void)
{
uint8_t old_ks[KEYSTRING_MD_SIZE];
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
uint8_t *new_ks = &new_ks0[1];
uint8_t new_ks0[KEYSTRING_SIZE];
uint8_t *new_salt = KS_GET_SALT (new_ks0);
int newsalt_len = SALT_SIZE;
uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0);
uint8_t p1 = P1 (apdu); /* 0: change (old+new), 1: exchange (new) */
uint8_t p2 = P2 (apdu);
int len;
@@ -256,6 +258,9 @@ cmd_change_password (void)
int who_old;
int r;
int pw3_null = 0;
const uint8_t *salt;
int salt_len;
const uint8_t *ks_pw3;
DEBUG_INFO ("Change PW\r\n");
DEBUG_BYTE (who);
@@ -273,8 +278,19 @@ cmd_change_password (void)
{
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
pw_len = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, len, -1, ks_pw1);
who_old = who;
pw_len = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, len, -1, ks_pw1, 0);
if (ks_pw1 == NULL)
{
salt = NULL;
salt_len = 0;
}
else
{
salt = KS_GET_SALT (ks_pw1);
salt_len = SALT_SIZE;
}
if (pw_len < 0)
{
@@ -290,10 +306,9 @@ cmd_change_password (void)
}
else
{
const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
newpw = pw + pw_len;
newpw_len = len - pw_len;
ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
/* Check length of password for admin-less mode. */
if (ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
@@ -306,7 +321,19 @@ cmd_change_password (void)
}
else /* PW3 (0x83) */
{
pw_len = verify_admin_0 (pw, len, -1);
ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
pw_len = verify_admin_0 (pw, len, -1, ks_pw3, 0);
if (ks_pw3 == NULL)
{
salt = NULL;
salt_len = 0;
}
else
{
salt = KS_GET_SALT (ks_pw3);
salt_len = SALT_SIZE;
}
if (pw_len < 0)
{
@@ -329,6 +356,7 @@ 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);
newsalt_len = 0;
pw3_null = 1;
}
@@ -336,9 +364,12 @@ cmd_change_password (void)
}
}
s2k (who_old, pw, pw_len, old_ks);
s2k (who, newpw, newpw_len, new_ks);
if (newsalt_len != 0)
random_get_salt (new_salt);
s2k (salt, salt_len, pw, pw_len, old_ks);
s2k (new_salt, newsalt_len, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
*KS_GET_ITER (new_ks0) = S2K_ITER;
r = gpg_change_keystring (who_old, old_ks, who, new_ks);
if (r <= -2)
@@ -364,7 +395,7 @@ cmd_change_password (void)
}
else if (r > 0 && who == BY_USER)
{
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KS_META_SIZE);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
@@ -372,16 +403,14 @@ cmd_change_password (void)
DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
GPG_SUCCESS ();
}
#if 0
else if (r > 0 && who == BY_ADMIN)
{
if (!pw3_null)
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, new_ks0, 1);
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, new_ks0, KS_META_SIZE);
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)
@@ -396,24 +425,36 @@ cmd_change_password (void)
}
#define USER_S2K_MAGIC "\xffUSER\r\n"
#define RESETCODE_S2K_MAGIC "\xffRESET\r\n"
#define S2KCOUNT 65535
void
s2k (int who, const unsigned char *input, unsigned int ilen,
unsigned char output[32])
s2k (const unsigned char *salt, size_t slen,
const unsigned char *input, size_t ilen, unsigned char output[32])
{
sha256_context ctx;
size_t count = S2KCOUNT;
sha256_start (&ctx);
sha256_update (&ctx, input, ilen);
if (who == BY_USER)
sha256_update (&ctx, (unsigned char *)USER_S2K_MAGIC,
sizeof (USER_S2K_MAGIC));
else if (who == BY_RESETCODE)
sha256_update (&ctx, (unsigned char *)RESETCODE_S2K_MAGIC,
sizeof (RESETCODE_S2K_MAGIC));
/* Not add any for BY_ADMIN */
while (count > slen + ilen)
{
if (slen)
sha256_update (&ctx, salt, slen);
sha256_update (&ctx, input, ilen);
count -= slen + ilen;
}
if (count <= slen)
sha256_update (&ctx, salt, count);
else
{
if (slen)
{
sha256_update (&ctx, salt, slen);
count -= slen;
}
sha256_update (&ctx, input, count);
}
sha256_finish (&ctx, output);
}
@@ -427,8 +468,11 @@ cmd_reset_user_password (void)
const uint8_t *newpw;
int pw_len, newpw_len;
int r;
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
uint8_t *new_ks = &new_ks0[1];
uint8_t new_ks0[KEYSTRING_SIZE];
uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0);
uint8_t *new_salt = KS_GET_SALT (new_ks0);
const uint8_t *salt;
int salt_len;
DEBUG_INFO ("Reset PW1\r\n");
DEBUG_BYTE (p1);
@@ -456,11 +500,15 @@ cmd_reset_user_password (void)
}
pw_len = ks_rc[0] & PW_LEN_MASK;
salt = KS_GET_SALT (ks_rc);
salt_len = SALT_SIZE;
newpw = pw + pw_len;
newpw_len = len - pw_len;
s2k (BY_RESETCODE, pw, pw_len, old_ks);
s2k (BY_USER, newpw, newpw_len, new_ks);
random_get_salt (new_salt);
s2k (salt, salt_len, pw, pw_len, old_ks);
s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
*KS_GET_ITER (new_ks0) = S2K_ITER;
r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks);
if (r <= -2)
{
@@ -476,7 +524,7 @@ cmd_reset_user_password (void)
}
else if (r == 0)
{
if (memcmp (ks_rc+1, old_ks, KEYSTRING_MD_SIZE) != 0)
if (memcmp (KS_GET_KEYSTRING (ks_rc), old_ks, KEYSTRING_MD_SIZE) != 0)
goto sec_fail;
DEBUG_INFO ("done (no prvkey).\r\n");
new_ks0[0] |= PW_LEN_KEYSTRING_BIT;
@@ -492,7 +540,7 @@ cmd_reset_user_password (void)
else
{
DEBUG_INFO ("done.\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KS_META_SIZE);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
@@ -515,7 +563,8 @@ cmd_reset_user_password (void)
newpw_len = len;
newpw = pw;
s2k (BY_USER, newpw, newpw_len, new_ks);
random_get_salt (new_salt);
s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks);
if (r <= -2)
@@ -543,7 +592,7 @@ cmd_reset_user_password (void)
else
{
DEBUG_INFO ("done.\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KS_META_SIZE);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)

View File

@@ -73,10 +73,15 @@ random_bytes_free (const uint8_t *p)
/*
* Return 4-byte salt
*/
uint32_t
get_salt (void)
void
random_get_salt (uint8_t *p)
{
return neug_get (NEUG_KICK_FILLING);
uint32_t rnd;
rnd = neug_get (NEUG_KICK_FILLING);
memcpy (p, &rnd, sizeof (uint32_t));
rnd = neug_get (NEUG_KICK_FILLING);
memcpy (p + sizeof (uint32_t), &rnd, sizeof (uint32_t));
}

View File

@@ -5,8 +5,8 @@ void random_fini (void);
const uint8_t *random_bytes_get (void);
void random_bytes_free (const uint8_t *p);
/* 4-byte salt */
uint32_t get_salt (void);
/* 8-byte salt */
void random_get_salt (uint8_t *p);
/* iterator returning a byta at a time */
int random_gen (void *arg, unsigned char *output, size_t output_len);