diff --git a/ChangeLog b/ChangeLog index 06ac1af..046c88e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-05-10 NIIBE Yutaka + + Prevent observation of PW3 is emptiness by PW3's error counter. + Support verify_admin by PW1 when PW3 is empty. + * src/ac.c (admin_authorized): New. + (verify_admin_0): Set admin_authorized. + * src/openpgp-do.c (proc_resetting_code): Use admin_authorized. + (gpg_do_write_prvkey): Clear dek_encrypted_3 when keystring_admin + is NULL. + (proc_key_import): Checking admin_authorized, set keystring_admin. + * src/openpgp.c (cmd_reset_user_password): Use admin_authorized. + 2011-04-18 NIIBE Yutaka * gnuk.svg: Updated. diff --git a/src/ac.c b/src/ac.c index a1643d2..1562a73 100644 --- a/src/ac.c +++ b/src/ac.c @@ -161,6 +161,9 @@ calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len, memset (&sha1_ctx, 0, sizeof (sha1_ctx)); } +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) { @@ -191,25 +194,51 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known) gpg_increment_pw_err_counter (PW_ERR_PW3); return -1; } - else - /* OK, the user is now authenticated */ - gpg_reset_pw_err_counter (PW_ERR_PW3); + + admin_authorized = BY_ADMIN; + success: + /* OK, the user is now authenticated */ + gpg_reset_pw_err_counter (PW_ERR_PW3); + return pw_len; } else - /* For empty PW3, pass phrase should be OPENPGP_CARD_INITIAL_PW3 */ { - if ((pw_len_known >=0 - && pw_len_known != strlen (OPENPGP_CARD_INITIAL_PW3)) - || buf_len < (int)strlen (OPENPGP_CARD_INITIAL_PW3) - || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3, - strlen (OPENPGP_CARD_INITIAL_PW3)) != 0) - /* It is failure, but we don't try to lock for the case of empty PW3 */ - return -1; + const uint8_t *ks_pw1; + uint8_t pw1_keystring[KEYSTRING_SIZE_PW1]; - pw_len = strlen (OPENPGP_CARD_INITIAL_PW3); + ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); + if (ks_pw1 == NULL) + { /* + * For empty PW3 with empty PW1, pass phrase should be + * OPENPGP_CARD_INITIAL_PW3 + */ + if ((pw_len_known >=0 + && pw_len_known != strlen (OPENPGP_CARD_INITIAL_PW3)) + || buf_len < (int)strlen (OPENPGP_CARD_INITIAL_PW3) + || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3, + strlen (OPENPGP_CARD_INITIAL_PW3)) != 0) + goto failure; + + pw_len = strlen (OPENPGP_CARD_INITIAL_PW3); + admin_authorized = BY_ADMIN; + goto success; + } + else /* empty PW3, but PW1 exists */ + { + pw_len = ks_pw1[0]; + if (pw_len_known < 0 && pw_len_known != pw_len) + goto failure; + + pw1_keystring[0] = pw_len; + sha1 (pw, pw_len, pw1_keystring+1); + if (gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, + pw1_keystring + 1) < 0) + goto failure; + + admin_authorized = BY_USER; + goto success; + } } - - return pw_len; } void @@ -229,8 +258,6 @@ gpg_set_pw3 (const uint8_t *newpw, int newpw_len) gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3); } -uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE]; - int verify_admin (const uint8_t *pw, int pw_len) { diff --git a/src/gnuk.h b/src/gnuk.h index 94adf10..fdf2681 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -211,6 +211,7 @@ extern void fatal (uint8_t code) __attribute__ ((noreturn)); #define FATAL_RANDOM 2 extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE]; +extern uint8_t admin_authorized; /*** Flash memory tag values ***/ #define NR_NONE 0x00 diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 0804382..161e92b 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -525,7 +525,7 @@ proc_resetting_code (const uint8_t *data, int len) newpw = data; sha1 (newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; - r = gpg_change_keystring (BY_ADMIN, old_ks, BY_RESETCODE, new_ks); + r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks); if (r < -2) { DEBUG_INFO ("memory error.\r\n"); @@ -656,7 +656,7 @@ static int8_t num_prv_keys; static int gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, - const uint8_t *keystring) + const uint8_t *keystring_admin) { uint8_t nr = get_do_ptr_nr_for_kk (kk); const uint8_t *p; @@ -752,7 +752,10 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, else memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE); - encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE); + if (keystring_admin) + encrypt (keystring_admin, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE); + else + memset (pd->dek_encrypted_3, 0, DATA_ENCRYPTION_KEY_SIZE); p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); do_ptr[nr - NR_DO__FIRST__] = p; @@ -834,6 +837,13 @@ proc_key_import (const uint8_t *data, int len) { int r; enum kind_of_key kk; + const uint8_t *pw3_keystring; + const uint8_t *keystring_admin; + + if (admin_authorized == BY_ADMIN) + keystring_admin = keystring_md_pw3; + else + keystring_admin = NULL; DEBUG_BINARY (data, len); @@ -869,7 +879,7 @@ proc_key_import (const uint8_t *data, int len) /* It should starts with 00 01 00 01 (E) */ /* Skip E, 4-byte */ - r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_md_pw3); + r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin); if (r < 0) return 0; else @@ -941,8 +951,8 @@ gpg_do_table[] = { { GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED, proc_key_import }, #if 0 - /* Card holder certificate */ - { GPG_DO_CH_CERTIFICATE, DO_PROC_READ, AC_ALWAYS, AC_NEVER, NULL }, + /* Card holder certificate is handled in special way, as its size is big */ + { GPG_DO_CH_CERTIFICATE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, #endif }; diff --git a/src/openpgp.c b/src/openpgp.c index 8758358..9bde988 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -537,7 +537,7 @@ cmd_reset_user_password (void) newpw = pw; sha1 (newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; - r = gpg_change_keystring (BY_ADMIN, old_ks, BY_USER, new_ks); + r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks); if (r < -2) { DEBUG_INFO ("memory error.\r\n");