diff --git a/ChangeLog b/ChangeLog index d6b1af6..3bc64ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2013-10-09 Niibe Yutaka + + * 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 * src/openpgp-do.c (gpg_do_write_prvkey): Remove information (but diff --git a/src/ac.c b/src/ac.c index f47e63c..fdcb4e7 100644 --- a/src/ac.c +++ b/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; - - 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; } diff --git a/src/gnuk.h b/src/gnuk.h index b29a613..9858aff 100644 --- a/src/gnuk.h +++ b/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 diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 22dd4df..1f111c1 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -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; } diff --git a/src/openpgp.c b/src/openpgp.c index f3d3933..7702a0a 100644 --- a/src/openpgp.c +++ b/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); - 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) diff --git a/src/random.c b/src/random.c index 4d5c8e1..815dbbc 100644 --- a/src/random.c +++ b/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)); } diff --git a/src/random.h b/src/random.h index fb3e639..026922a 100644 --- a/src/random.h +++ b/src/random.h @@ -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);