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> 2013-10-09 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_do_write_prvkey): Remove information (but * 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 int
verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known, 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 pw_len;
int r1, r2; int r1, r2;
uint8_t keystring[KEYSTRING_MD_SIZE]; uint8_t keystring[KEYSTRING_MD_SIZE];
const uint8_t *salt;
int salt_len;
if (gpg_pw_locked (PW_ERR_PW1)) if (gpg_pw_locked (PW_ERR_PW1))
return 0; 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) if (ks_pw1 == NULL)
{ {
pw_len = strlen (OPENPGP_CARD_INITIAL_PW1); pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
salt = NULL;
salt_len = 0;
if ((pw_len_known >= 0 && pw_len_known != pw_len) if ((pw_len_known >= 0 && pw_len_known != pw_len)
|| buf_len < pw_len || buf_len < pw_len
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len)) || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
goto failure; goto failure;
else
goto success_one_step;
} }
else else
pw_len = ks_pw1[0] & PW_LEN_MASK;
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|| buf_len < pw_len)
{ {
failure: pw_len = ks_pw1[0] & PW_LEN_MASK;
gpg_pw_increment_err_counter (PW_ERR_PW1); salt = KS_GET_SALT (ks_pw1);
return -1; salt_len = SALT_SIZE;
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|| buf_len < pw_len)
goto failure;
} }
success_one_step: s2k (salt, salt_len, pw, pw_len, keystring);
s2k (BY_USER, pw, pw_len, keystring); if (save_ks)
memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE);
if (access == AC_PSO_CDS_AUTHORIZED) if (access == AC_PSO_CDS_AUTHORIZED)
{ {
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring); 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); 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); gpg_pw_increment_err_counter (PW_ERR_PW1);
return -1; 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); gpg_pw_reset_err_counter (PW_ERR_PW1);
return pw_len; 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_INFO ("verify_pso_cds\r\n");
DEBUG_BYTE (pw_len); 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) if (r > 0)
auth_status |= AC_PSO_CDS_AUTHORIZED; auth_status |= AC_PSO_CDS_AUTHORIZED;
return r; return r;
@@ -143,70 +148,41 @@ verify_other (const uint8_t *pw, int pw_len)
DEBUG_INFO ("verify_other\r\n"); DEBUG_INFO ("verify_other\r\n");
DEBUG_BYTE (pw_len); 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) if (r > 0)
auth_status |= AC_OTHER_AUTHORIZED; auth_status |= AC_OTHER_AUTHORIZED;
return r; 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 static int
verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known, 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 pw_len;
int r1, r2; int r1, r2;
uint8_t keystring[KEYSTRING_MD_SIZE]; uint8_t keystring[KEYSTRING_MD_SIZE];
const uint8_t *salt;
int salt_len;
pw_len = ks[0] & PW_LEN_MASK; 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) if ((pw_len_known >= 0 && pw_len_known != pw_len) || buf_len < pw_len)
return -1; 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); r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_ADMIN, keystring);
r2 = 0; r2 = 0;
if (r1 < 0 || r2 < 0) if (r1 < 0 || r2 < 0)
return -1; return -1;
else if (r1 == 0 && r2 == 0) 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 -1;
return pw_len; return pw_len;
@@ -216,18 +192,18 @@ uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
uint8_t admin_authorized; uint8_t admin_authorized;
int 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; int pw_len;
pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
if (pw3_keystring != NULL) if (pw3_keystring != NULL)
{ {
if (gpg_pw_locked (PW_ERR_PW3)) if (gpg_pw_locked (PW_ERR_PW3))
return 0; 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) if (pw_len < 0)
{ {
failure: failure:
@@ -247,7 +223,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
if (ks_pw1 != NULL) if (ks_pw1 != NULL)
{ /* empty PW3, but PW1 exists */ { /* empty PW3, but PW1 exists */
int r = verify_user_0 (AC_PSO_CDS_AUTHORIZED, 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) if (r > 0)
admin_authorized = BY_USER; admin_authorized = BY_USER;
@@ -269,37 +245,24 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
goto failure; goto failure;
admin_authorized = BY_ADMIN; admin_authorized = BY_ADMIN;
if (save_ks)
s2k (NULL, 0, pw, pw_len, keystring_md_pw3);
goto success; 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 int
verify_admin (const uint8_t *pw, int pw_len) verify_admin (const uint8_t *pw, int pw_len)
{ {
int r; 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) if (r <= 0)
return r; return r;
s2k (admin_authorized, pw, pw_len, keystring_md_pw3);
auth_status |= AC_ADMIN_AUTHORIZED; auth_status |= AC_ADMIN_AUTHORIZED;
return 1; 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_pso_cds (const uint8_t *pw, int pw_len);
extern int verify_other (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, 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 (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_pso_cds (void);
extern void ac_reset_other (void); extern void ac_reset_other (void);
@@ -177,19 +178,26 @@ struct prvkey_data {
#define PW_LEN_MASK 0x7f #define PW_LEN_MASK 0x7f
#define PW_LEN_KEYSTRING_BIT 0x80 #define PW_LEN_KEYSTRING_BIT 0x80
extern void s2k (int who, const unsigned char *input, unsigned int ilen, #define SALT_SIZE 8
unsigned char output[32]);
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_PASSLEN_SIZE 1
#define KEYSTRING_SALT_SIZE 8 /* optional */ #define KEYSTRING_SALT_SIZE SALT_SIZE
#define KEYSTRING_ITER_SIZE 1 /* optional */ #define KEYSTRING_ITER_SIZE 1
#define KEYSTRING_MD_SIZE 32 #define KEYSTRING_MD_SIZE 32
#define KEYSTRING_SIZE_PW1 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE) #define KEYSTRING_SIZE (KEYSTRING_PASSLEN_SIZE + KEYSTRING_SALT_SIZE \
#define KEYSTRING_SIZE_RC (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE) + KEYSTRING_ITER_SIZE + KEYSTRING_MD_SIZE)
#define KEYSTRING_SIZE_PW3 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE \ #define KS_META_SIZE (KEYSTRING_PASSLEN_SIZE + KEYSTRING_SALT_SIZE \
+KEYSTRING_ITER_SIZE+KEYSTRING_MD_SIZE) + KEYSTRING_ITER_SIZE)
#define KEYSTRING_SIZE (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_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 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); 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_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)); extern void fatal (uint8_t code) __attribute__ ((noreturn));
#define FATAL_FLASH 1 #define FATAL_FLASH 1
#define FATAL_RANDOM 2 #define FATAL_RANDOM 2
@@ -328,8 +335,6 @@ extern uint8_t admin_authorized;
#define NUM_ALL_PRV_KEYS 3 /* SIG, DEC and AUT */ #define NUM_ALL_PRV_KEYS 3 /* SIG, DEC and AUT */
extern uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
#if !defined(OPENPGP_CARD_INITIAL_PW1) #if !defined(OPENPGP_CARD_INITIAL_PW1)
#define OPENPGP_CARD_INITIAL_PW1 "123456" #define OPENPGP_CARD_INITIAL_PW1 "123456"
#endif #endif

View File

@@ -551,18 +551,21 @@ static int
proc_resetting_code (const uint8_t *data, int len) proc_resetting_code (const uint8_t *data, int len)
{ {
const uint8_t *old_ks = keystring_md_pw3; const uint8_t *old_ks = keystring_md_pw3;
uint8_t new_ks0[KEYSTRING_MD_SIZE+1]; uint8_t new_ks0[KEYSTRING_SIZE];
uint8_t *new_ks = &new_ks0[1]; uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0);
const uint8_t *newpw; const uint8_t *newpw;
int newpw_len; int newpw_len;
int r; int r;
uint8_t *salt = KS_GET_SALT (new_ks0);
DEBUG_INFO ("Resetting Code!\r\n"); DEBUG_INFO ("Resetting Code!\r\n");
newpw_len = len; newpw_len = len;
newpw = data; newpw = data;
s2k (BY_RESETCODE, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len; 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); r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
if (r <= -2) if (r <= -2)
{ {
@@ -583,7 +586,7 @@ proc_resetting_code (const uint8_t *data, int len)
else else
{ {
DEBUG_INFO ("done.\r\n"); 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); 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) if (ks_pw1)
{ {
ks_pw1_len = ks_pw1[0]; 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 else
{ {
uint8_t ks[KEYSTRING_MD_SIZE]; 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); strlen (OPENPGP_CARD_INITIAL_PW1), ks);
encrypt_dek (ks, pd->dek_encrypted_1); 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) if (ks_rc)
{ {
ks_rc_len = ks_rc[0]; 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 else
memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE); 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. */ 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)) if ((ks_pw1_len & PW_LEN_KEYSTRING_BIT))
{ {
ks_pw1_len &= PW_LEN_MASK; 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)) if ((ks_rc_len & PW_LEN_KEYSTRING_BIT))
{ {
ks_rc_len &= PW_LEN_MASK; 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) if (keystring_admin)
{ {
const uint8_t *ks_admin = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); const uint8_t *ks_admin = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
uint8_t admin_pw_len;
if (ks_admin != NULL) if (ks_admin != NULL)
{ {
admin_pw_len = ks_admin[0] & PW_LEN_MASK; ks_info[0] = ks_admin[0] & PW_LEN_MASK;
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, &admin_pw_len, 1); 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 else
{ {
@@ -1044,10 +1056,13 @@ proc_key_import (const uint8_t *data, int len)
if (ks_pw3 != NULL) 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; 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); 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 */ /* Don't call ac_reset_pso_cds here, but load the private key */
if (ks_pw1) if (ks_pw1)
ks = ks_pw1+1; ks = KS_GET_KEYSTRING (ks_pw1);
else else
{ {
const uint8_t * pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1; 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; ks = keystring;
} }

View File

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

View File

@@ -73,10 +73,15 @@ random_bytes_free (const uint8_t *p)
/* /*
* Return 4-byte salt * Return 4-byte salt
*/ */
uint32_t void
get_salt (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); const uint8_t *random_bytes_get (void);
void random_bytes_free (const uint8_t *p); void random_bytes_free (const uint8_t *p);
/* 4-byte salt */ /* 8-byte salt */
uint32_t get_salt (void); void random_get_salt (uint8_t *p);
/* iterator returning a byta at a time */ /* iterator returning a byta at a time */
int random_gen (void *arg, unsigned char *output, size_t output_len); int random_gen (void *arg, unsigned char *output, size_t output_len);