diff --git a/ChangeLog b/ChangeLog index 8481149..00fab3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2013-10-15 Niibe Yutaka + + * src/openpgp.c (cmd_change_password, cmd_reset_user_password): It + is now error to change User's pass phrase with no keys. + + * src/openpgp-do.c (proc_resetting_code): Likewise for resetting + code. + (gpg_do_delete_prvkey): New. + (gpg_do_write_prvkey): Make sure to delete the key before writing. + User's pass phrase is always the one of factory setting. + (gpg_do_chks_prvkey): Support removing the key. + (proc_key_import): Use gpg_do_delete_prvkey. + (gpg_do_keygen): Use factory setting pass phrase. + 2013-10-11 Niibe Yutaka * src/ac.c (verify_user_0, verify_admin_00): Fix conditions. diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 167b09d..29e7f25 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -578,9 +578,8 @@ proc_resetting_code (const uint8_t *data, int len) } else if (r == 0) { - DEBUG_INFO ("done (no prvkey).\r\n"); - new_ks0[0] |= PW_LEN_KEYSTRING_BIT; - gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KEYSTRING_SIZE); + DEBUG_INFO ("error (no prvkey).\r\n"); + return 0; } else { @@ -730,6 +729,48 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring) static int8_t num_prv_keys; +static void +gpg_do_delete_prvkey (enum kind_of_key kk) +{ + uint8_t nr = get_do_ptr_nr_for_kk (kk); + const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__]; + + if (do_data == NULL) + return; + + do_ptr[nr - NR_DO__FIRST__] = NULL; + flash_do_release (do_data); + + if (admin_authorized == BY_ADMIN && kk == GPG_KEY_FOR_SIGNING) + { /* Recover admin keystring DO. */ + const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); + + if (ks_pw3 != NULL) + { + uint8_t ks0[KEYSTRING_SIZE]; + + ks0[0] = ks_pw3[0] | PW_LEN_KEYSTRING_BIT; + memcpy (KS_GET_SALT (ks0), KS_GET_SALT (ks_pw3), SALT_SIZE); + memcpy (KS_GET_KEYSTRING (ks0), keystring_md_pw3, KEYSTRING_MD_SIZE); + gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks0, KEYSTRING_SIZE); + } + } + + if (--num_prv_keys == 0) + { + flash_keystore_release (); + + /* Delete PW1 and RC if any. */ + gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0); + gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0); + + ac_reset_pso_cds (); + ac_reset_other (); + if (admin_authorized == BY_USER) + ac_reset_admin (); + } +} + static int gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, const uint8_t *keystring_admin, const uint8_t *pubkey) @@ -740,23 +781,17 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, struct prvkey_data *pd; uint8_t *key_addr; const uint8_t *dek, *iv; - const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__]; - const uint8_t *ks_pw1; - const uint8_t *ks_rc; struct key_data_internal kdi; uint8_t *pubkey_allocated_here = NULL; - uint8_t ks_pw1_len = 0; - uint8_t ks_rc_len = 0; int pubkey_len = KEY_CONTENT_LEN; - uint8_t ks_info0[KS_META_SIZE]; - uint8_t ks_info1[KS_META_SIZE]; + uint8_t ks[KEYSTRING_MD_SIZE]; + enum kind_of_key kk0; DEBUG_INFO ("Key import\r\n"); DEBUG_SHORT (key_len); - if (do_data) - /* No replace support, you need to remove it first. */ - return -1; + /* Delete it first, if any. */ + gpg_do_delete_prvkey (kk); #ifdef RSA_AUTH if (key_len != KEY_CONTENT_LEN) @@ -827,8 +862,20 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE); memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE); memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE); - ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC); + + s2k (NULL, 0, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1, + strlen (OPENPGP_CARD_INITIAL_PW1), ks); + + /* Handle existing keys and keystring DOs. */ + gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0); + gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0); + for (kk0 = 0; kk0 <= GPG_KEY_FOR_AUTHENTICATION; kk++) + if (kk0 != kk) + { + gpg_do_chks_prvkey (kk0, admin_authorized, keystring_md_pw3, + BY_USER, ks); + gpg_do_chks_prvkey (kk0, BY_RESETCODE, NULL, 0, NULL); + } encrypt (dek, iv, (uint8_t *)&kdi, sizeof (struct key_data_internal)); @@ -853,29 +900,9 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, memcpy (pd->iv, iv, INITIAL_VECTOR_SIZE); memcpy (pd->checksum_encrypted, kdi.checksum, DATA_ENCRYPTION_KEY_SIZE); - if (ks_pw1 && ((ks_pw1_len = ks_pw1[0]) & PW_LEN_KEYSTRING_BIT)) - { - ks_info0[0] = ks_pw1_len & PW_LEN_MASK; - memcpy (KS_GET_SALT (ks_info0), KS_GET_SALT (ks_pw1), SALT_SIZE); - encrypt_dek (KS_GET_KEYSTRING (ks_pw1), pd->dek_encrypted_1); - } - else - { - uint8_t ks[KEYSTRING_MD_SIZE]; + encrypt_dek (ks, pd->dek_encrypted_1); - s2k (NULL, 0, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1, - strlen (OPENPGP_CARD_INITIAL_PW1), ks); - encrypt_dek (ks, pd->dek_encrypted_1); - } - - if (ks_rc && ((ks_rc_len = ks_rc[0]) & PW_LEN_KEYSTRING_BIT)) - { - ks_info1[0] = ks_rc_len & PW_LEN_MASK; - memcpy (KS_GET_SALT (ks_info1), KS_GET_SALT (ks_rc), SALT_SIZE); - encrypt_dek (KS_GET_KEYSTRING (ks_rc), pd->dek_encrypted_2); - } - else - memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE); + memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE); if (keystring_admin) encrypt_dek (keystring_admin, pd->dek_encrypted_3); @@ -894,12 +921,13 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, if (keystring_admin && kk == GPG_KEY_FOR_SIGNING) { const uint8_t *ks_admin = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); + uint8_t ks_info[KS_META_SIZE]; if (ks_admin != NULL && (ks_admin[0] & PW_LEN_KEYSTRING_BIT)) { - ks_info0[0] = ks_admin[0] & PW_LEN_MASK; - memcpy (KS_GET_SALT (ks_info0), KS_GET_SALT (ks_admin), SALT_SIZE); - gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks_info0, KS_META_SIZE); + ks_info[0] = ks_admin[0] & PW_LEN_MASK; + memcpy (KS_GET_SALT (ks_info), KS_GET_SALT (ks_admin), SALT_SIZE); + gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks_info, KS_META_SIZE); } else { @@ -907,20 +935,6 @@ 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 and salt. */ - /* - * Note that flash_do_write (above) or gpg_do_write_simple - * (below) may result garbage collection for flash ROM. Thus, - * the access to ks_pw1/ks_rc must not be done here but before. - */ - if ((ks_pw1_len & PW_LEN_KEYSTRING_BIT)) - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, ks_info0, KS_META_SIZE); - - if ((ks_rc_len & PW_LEN_KEYSTRING_BIT)) - gpg_do_write_simple (NR_DO_KEYSTRING_RC, ks_info1, KS_META_SIZE); - } - return 0; } @@ -935,6 +949,7 @@ gpg_do_chks_prvkey (enum kind_of_key kk, struct prvkey_data *pd; const uint8_t *p; uint8_t *dek_p; + int update_needed = 0; if (do_data == NULL) return 0; /* No private key */ @@ -944,23 +959,44 @@ gpg_do_chks_prvkey (enum kind_of_key kk, return -1; memcpy (pd, &do_data[1], sizeof (struct prvkey_data)); - flash_do_release (do_data); dek_p = ((uint8_t *)pd) + 4 + INITIAL_VECTOR_SIZE + DATA_ENCRYPTION_KEY_SIZE * who_old; memcpy (dek, dek_p, DATA_ENCRYPTION_KEY_SIZE); - decrypt_dek (old_ks, dek); - encrypt_dek (new_ks, dek); - dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old); - memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE); + if (who_new == 0) /* Remove */ + { + int i; - do_ptr[nr - NR_DO__FIRST__] = NULL; - p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); - do_ptr[nr - NR_DO__FIRST__] = p; + for (i = 0; i < DATA_ENCRYPTION_KEY_SIZE; i++) + if (dek_p[i] != 0) + { + update_needed = 1; + dek_p[i] = 0; + } + } + else + { + decrypt_dek (old_ks, dek); + encrypt_dek (new_ks, dek); + dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old); + if (memcmp (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE) != 0) + { + memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE); + update_needed = 1; + } + } + + if (update_needed) + { + flash_do_release (do_data); + do_ptr[nr - NR_DO__FIRST__] = NULL; + p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); + do_ptr[nr - NR_DO__FIRST__] = p; + } memset (pd, 0, sizeof (struct prvkey_data)); free (pd); - if (p == NULL) + if (update_needed && p == NULL) return -1; return 1; @@ -1033,45 +1069,7 @@ proc_key_import (const uint8_t *data, int len) || (kk == GPG_KEY_FOR_AUTHENTICATION && len <= 12)) #endif { /* Deletion of the key */ - uint8_t nr = get_do_ptr_nr_for_kk (kk); - const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__]; - - if (do_data == NULL) - return 1; - - do_ptr[nr - NR_DO__FIRST__] = NULL; - flash_do_release (do_data); - - if (admin_authorized == BY_ADMIN && kk == GPG_KEY_FOR_SIGNING) - { /* Recover admin keystring DO. */ - const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); - - if (ks_pw3 != NULL) - { - uint8_t ks0[KEYSTRING_SIZE]; - - ks0[0] = ks_pw3[0] | PW_LEN_KEYSTRING_BIT; - memcpy (KS_GET_SALT (ks0), KS_GET_SALT (ks_pw3), SALT_SIZE); - memcpy (KS_GET_KEYSTRING (ks0), - keystring_md_pw3, KEYSTRING_MD_SIZE); - gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks0, KEYSTRING_SIZE); - } - } - - if (--num_prv_keys == 0) - { - flash_keystore_release (); - - /* Delete PW1 and RC if any. */ - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0); - gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0); - - ac_reset_pso_cds (); - ac_reset_other (); - if (admin_authorized == BY_USER) - ac_reset_admin (); - } - + gpg_do_delete_prvkey (kk); return 1; } @@ -1727,30 +1725,14 @@ gpg_do_keygen (uint8_t kk_byte) if (kk == GPG_KEY_FOR_SIGNING) { - const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); + const uint8_t *pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1; uint8_t keystring[KEYSTRING_MD_SIZE]; - const uint8_t *ks; /* GnuPG expects it's ready for signing. */ /* Don't call ac_reset_pso_cds here, but load the private key */ - if (ks_pw1 == NULL) - { - const uint8_t * pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1; - - s2k (NULL, 0, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring); - ks = keystring; - } - else - if ((ks_pw1[0] & PW_LEN_KEYSTRING_BIT) != 0) - ks = KS_GET_KEYSTRING (ks_pw1); - else - { - GPG_ERROR (); - return; - } - - gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, ks); + s2k (NULL, 0, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring); + gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring); } else ac_reset_other (); diff --git a/src/openpgp.c b/src/openpgp.c index 191f66c..cb141c0 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -382,14 +382,8 @@ cmd_change_password (void) } else if (r == 0 && who == BY_USER) /* no prvkey */ { - new_ks0[0] |= PW_LEN_KEYSTRING_BIT; - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE); - ac_reset_pso_cds (); - ac_reset_other (); - if (admin_authorized == BY_USER) - ac_reset_admin (); - DEBUG_INFO ("Changed DO_KEYSTRING_PW1.\r\n"); - GPG_SUCCESS (); + DEBUG_INFO ("user pass change not supported with no keys.\r\n"); + GPG_CONDITION_NOT_SATISFIED (); } else if (r > 0 && who == BY_USER) { @@ -519,27 +513,14 @@ cmd_reset_user_password (void) } else if (r < 0) { - sec_fail: DEBUG_INFO ("failed.\r\n"); gpg_pw_increment_err_counter (PW_ERR_RC); GPG_SECURITY_FAILURE (); } else if (r == 0) { - if ((ks_rc[0] & PW_LEN_KEYSTRING_BIT) == 0 - || 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; - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE); - ac_reset_pso_cds (); - ac_reset_other (); - if (admin_authorized == BY_USER) - ac_reset_admin (); - gpg_pw_reset_err_counter (PW_ERR_RC); - gpg_pw_reset_err_counter (PW_ERR_PW1); - GPG_SUCCESS (); + DEBUG_INFO ("user pass change not supported with no keys.\r\n"); + GPG_CONDITION_NOT_SATISFIED (); } else { @@ -583,15 +564,8 @@ cmd_reset_user_password (void) } else if (r == 0) { - DEBUG_INFO ("done (no privkey).\r\n"); - new_ks0[0] |= PW_LEN_KEYSTRING_BIT; - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE); - ac_reset_pso_cds (); - ac_reset_other (); - if (admin_authorized == BY_USER) - ac_reset_admin (); - gpg_pw_reset_err_counter (PW_ERR_PW1); - GPG_SUCCESS (); + DEBUG_INFO ("user pass change not supported with no keys.\r\n"); + GPG_CONDITION_NOT_SATISFIED (); } else {