From 74b21d307cbfa64e2eb75ce5a1c4a33d9291d3cc Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 11 May 2011 23:33:38 +0900 Subject: [PATCH] VERIFY bug fixes --- ChangeLog | 5 +++ src/ac.c | 110 ++++++++++++++++++++++------------------------- src/gnuk.h | 2 +- src/openpgp-do.c | 5 +++ 4 files changed, 62 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5f825ce..4bf9bfc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2011-05-11 NIIBE Yutaka + * src/ac.c (verify_pso_cds, verify_other): Fail (with no counter + update) if key is not registered yet. + (verify_admin_0): Compare to OPENPGP_CARD_INITIAL_PW3 when empty + PW3 and non-empty PW1 but signing key is not registered yet. + * tool/gnuk_put_binary.py: New implementation by pyscard. * src/main.c (device_initialize_once): New. diff --git a/src/ac.c b/src/ac.c index e13ec96..6f49b24 100644 --- a/src/ac.c +++ b/src/ac.c @@ -63,7 +63,7 @@ int verify_pso_cds (const uint8_t *pw, int pw_len) { int r; - uint8_t keystring[KEYSTRING_SIZE_PW1]; + uint8_t keystring[KEYSTRING_MD_SIZE]; if (gpg_pw_locked (PW_ERR_PW1)) return 0; @@ -71,16 +71,17 @@ verify_pso_cds (const uint8_t *pw, int pw_len) DEBUG_INFO ("verify_pso_cds\r\n"); DEBUG_BYTE (pw_len); - keystring[0] = pw_len; - sha1 (pw, pw_len, keystring+1); - if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring+1)) < 0) + sha1 (pw, pw_len, keystring); + if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring)) < 0) { gpg_pw_increment_err_counter (PW_ERR_PW1); - return r; + return -1; } - else - gpg_pw_reset_err_counter (PW_ERR_PW1); + else if (r == 0) + /* No key is available. Fail even if password can match. */ + return -1; + gpg_pw_reset_err_counter (PW_ERR_PW1); auth_status |= AC_PSO_CDS_AUTHORIZED; return 1; } @@ -88,39 +89,29 @@ verify_pso_cds (const uint8_t *pw, int pw_len) int verify_other (const uint8_t *pw, int pw_len) { - const uint8_t *ks_pw1; - uint8_t pw1_keystring[KEYSTRING_SIZE_PW1]; + int r1, r2; + uint8_t keystring[KEYSTRING_MD_SIZE]; DEBUG_INFO ("verify_other\r\n"); if (gpg_pw_locked (PW_ERR_PW1)) return 0; - ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - if ((ks_pw1 == NULL && pw_len == strlen (OPENPGP_CARD_INITIAL_PW1)) - || (ks_pw1 != NULL && pw_len == ks_pw1[0])) - { /* No problem */ - pw1_keystring[0] = pw_len; - sha1 (pw, pw_len, pw1_keystring+1); - if (gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER, - pw1_keystring + 1) < 0) - goto error; - - if (gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER, - pw1_keystring + 1) < 0) - goto error; - - /* Reset counter as it's success now */ - gpg_pw_reset_err_counter (PW_ERR_PW1); - auth_status |= AC_OTHER_AUTHORIZED; - return 1; - } - else + sha1 (pw, pw_len, keystring); + if ((r1 = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER, keystring)) < 0 + || (r2 = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER, + keystring)) < 0) { - error: gpg_pw_increment_err_counter (PW_ERR_PW1); - return 0; + return -1; } + else if (r1 == 0 && r2 == 0) + /* No key is available. Fail even if password can match. */ + return -1; + + gpg_pw_reset_err_counter (PW_ERR_PW1); + auth_status |= AC_OTHER_AUTHORIZED; + return 1; } /* @@ -203,41 +194,42 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known) } else { - const uint8_t *ks_pw1; - uint8_t pw1_keystring[KEYSTRING_SIZE_PW1]; + const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - 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; + if (ks_pw1 != NULL) + { /* empty PW3, but PW1 exists */ + int r; + uint8_t keystring[KEYSTRING_MD_SIZE]; - 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) + if ((pw_len_known >= 0 && pw_len_known != pw_len) + || buf_len < 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) + sha1 (pw, pw_len, keystring); + if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring)) + < 0) goto failure; - - admin_authorized = BY_USER; - goto success; + else if (r > 0) + { + admin_authorized = BY_USER; + goto success; + } + /* if r == 0 (no signing key), then fall through */ } + + /* + * For the case of empty PW3 (with empty PW1 or no signing key yet), + * pass phrase should be OPENPGP_CARD_INITIAL_PW3 + */ + pw_len = strlen (OPENPGP_CARD_INITIAL_PW3); + if ((pw_len_known >=0 && pw_len_known != pw_len) + || buf_len < pw_len + || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3, pw_len)) + goto failure; + + admin_authorized = BY_ADMIN; + goto success; } } diff --git a/src/gnuk.h b/src/gnuk.h index 2cb73c1..b6b9f78 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -147,7 +147,7 @@ struct key_data_internal { struct prvkey_data { const uint8_t *key_addr; /* - * CRM: [C]heck, [R]andom, and [M]agic in struct key_data + * CRM: [C]heck, [R]andom, and [M]agic in struct key_data_internal * */ uint8_t crm_encrypted[ADDITIONAL_DATA_SIZE]; diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 5ed24db..58dc75c 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1070,6 +1070,11 @@ gpg_data_scan (const uint8_t *p_start) digital_signature_counter = (dsc_h14 << 10) | dsc_l10; } +/* + * Write all data to newly allocated Flash ROM page (from P_START), + * updating PW1_LIFETIME_P, PW_ERR_COUNTER_P, and DO_PTR. + * Called by flash_copying_gc. + */ void gpg_data_copy (const uint8_t *p_start) {