Add SALT for pass phrase handling
This commit is contained in:
12
ChangeLog
12
ChangeLog
@@ -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
|
||||
|
||||
119
src/ac.c
119
src/ac.c
@@ -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;
|
||||
salt = KS_GET_SALT (ks_pw1);
|
||||
salt_len = SALT_SIZE;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
33
src/gnuk.h
33
src/gnuk.h
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
113
src/openpgp.c
113
src/openpgp.c
@@ -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);
|
||||
|
||||
while (count > slen + ilen)
|
||||
{
|
||||
if (slen)
|
||||
sha256_update (&ctx, salt, slen);
|
||||
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 */
|
||||
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)
|
||||
|
||||
11
src/random.c
11
src/random.c
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user