new management of pass phrase

This commit is contained in:
NIIBE Yutaka
2013-10-15 12:52:55 +09:00
parent 5c74f11ed2
commit 2b39348e10
3 changed files with 123 additions and 153 deletions

View File

@@ -1,3 +1,17 @@
2013-10-15 Niibe Yutaka <gniibe@fsij.org>
* 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 <gniibe@fsij.org> 2013-10-11 Niibe Yutaka <gniibe@fsij.org>
* src/ac.c (verify_user_0, verify_admin_00): Fix conditions. * src/ac.c (verify_user_0, verify_admin_00): Fix conditions.

View File

@@ -578,9 +578,8 @@ proc_resetting_code (const uint8_t *data, int len)
} }
else if (r == 0) else if (r == 0)
{ {
DEBUG_INFO ("done (no prvkey).\r\n"); DEBUG_INFO ("error (no prvkey).\r\n");
new_ks0[0] |= PW_LEN_KEYSTRING_BIT; return 0;
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KEYSTRING_SIZE);
} }
else 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 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 static int
gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, 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) 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; struct prvkey_data *pd;
uint8_t *key_addr; uint8_t *key_addr;
const uint8_t *dek, *iv; 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; struct key_data_internal kdi;
uint8_t *pubkey_allocated_here = NULL; uint8_t *pubkey_allocated_here = NULL;
uint8_t ks_pw1_len = 0;
uint8_t ks_rc_len = 0;
int pubkey_len = KEY_CONTENT_LEN; int pubkey_len = KEY_CONTENT_LEN;
uint8_t ks_info0[KS_META_SIZE]; uint8_t ks[KEYSTRING_MD_SIZE];
uint8_t ks_info1[KS_META_SIZE]; enum kind_of_key kk0;
DEBUG_INFO ("Key import\r\n"); DEBUG_INFO ("Key import\r\n");
DEBUG_SHORT (key_len); DEBUG_SHORT (key_len);
if (do_data) /* Delete it first, if any. */
/* No replace support, you need to remove it first. */ gpg_do_delete_prvkey (kk);
return -1;
#ifdef RSA_AUTH #ifdef RSA_AUTH
if (key_len != KEY_CONTENT_LEN) 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_1, dek, DATA_ENCRYPTION_KEY_SIZE);
memcpy (pd->dek_encrypted_2, 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); 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)); encrypt (dek, iv, (uint8_t *)&kdi, sizeof (struct key_data_internal));
@@ -853,28 +900,8 @@ 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->iv, iv, INITIAL_VECTOR_SIZE);
memcpy (pd->checksum_encrypted, kdi.checksum, DATA_ENCRYPTION_KEY_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];
s2k (NULL, 0, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1,
strlen (OPENPGP_CARD_INITIAL_PW1), ks);
encrypt_dek (ks, pd->dek_encrypted_1); 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) if (keystring_admin)
@@ -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) if (keystring_admin && kk == GPG_KEY_FOR_SIGNING)
{ {
const uint8_t *ks_admin = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); 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)) if (ks_admin != NULL && (ks_admin[0] & PW_LEN_KEYSTRING_BIT))
{ {
ks_info0[0] = ks_admin[0] & PW_LEN_MASK; ks_info[0] = ks_admin[0] & PW_LEN_MASK;
memcpy (KS_GET_SALT (ks_info0), KS_GET_SALT (ks_admin), SALT_SIZE); memcpy (KS_GET_SALT (ks_info), KS_GET_SALT (ks_admin), SALT_SIZE);
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks_info0, KS_META_SIZE); gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks_info, KS_META_SIZE);
} }
else 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; return 0;
} }
@@ -935,6 +949,7 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
struct prvkey_data *pd; struct prvkey_data *pd;
const uint8_t *p; const uint8_t *p;
uint8_t *dek_p; uint8_t *dek_p;
int update_needed = 0;
if (do_data == NULL) if (do_data == NULL)
return 0; /* No private key */ return 0; /* No private key */
@@ -944,23 +959,44 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
return -1; return -1;
memcpy (pd, &do_data[1], sizeof (struct prvkey_data)); memcpy (pd, &do_data[1], sizeof (struct prvkey_data));
flash_do_release (do_data);
dek_p = ((uint8_t *)pd) + 4 + INITIAL_VECTOR_SIZE dek_p = ((uint8_t *)pd) + 4 + INITIAL_VECTOR_SIZE
+ DATA_ENCRYPTION_KEY_SIZE * who_old; + DATA_ENCRYPTION_KEY_SIZE * who_old;
memcpy (dek, dek_p, DATA_ENCRYPTION_KEY_SIZE); memcpy (dek, dek_p, DATA_ENCRYPTION_KEY_SIZE);
if (who_new == 0) /* Remove */
{
int i;
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); decrypt_dek (old_ks, dek);
encrypt_dek (new_ks, dek); encrypt_dek (new_ks, dek);
dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old); 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); 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; do_ptr[nr - NR_DO__FIRST__] = NULL;
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
do_ptr[nr - NR_DO__FIRST__] = p; do_ptr[nr - NR_DO__FIRST__] = p;
}
memset (pd, 0, sizeof (struct prvkey_data)); memset (pd, 0, sizeof (struct prvkey_data));
free (pd); free (pd);
if (p == NULL) if (update_needed && p == NULL)
return -1; return -1;
return 1; return 1;
@@ -1033,45 +1069,7 @@ proc_key_import (const uint8_t *data, int len)
|| (kk == GPG_KEY_FOR_AUTHENTICATION && len <= 12)) || (kk == GPG_KEY_FOR_AUTHENTICATION && len <= 12))
#endif #endif
{ /* Deletion of the key */ { /* Deletion of the key */
uint8_t nr = get_do_ptr_nr_for_kk (kk); gpg_do_delete_prvkey (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 ();
}
return 1; return 1;
} }
@@ -1727,30 +1725,14 @@ gpg_do_keygen (uint8_t kk_byte)
if (kk == GPG_KEY_FOR_SIGNING) 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]; uint8_t keystring[KEYSTRING_MD_SIZE];
const uint8_t *ks;
/* GnuPG expects it's ready for signing. */ /* GnuPG expects it's ready for signing. */
/* Don't call ac_reset_pso_cds here, but load the private key */ /* 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); s2k (NULL, 0, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring);
ks = keystring; gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, 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);
} }
else else
ac_reset_other (); ac_reset_other ();

View File

@@ -382,14 +382,8 @@ cmd_change_password (void)
} }
else if (r == 0 && who == BY_USER) /* no prvkey */ else if (r == 0 && who == BY_USER) /* no prvkey */
{ {
new_ks0[0] |= PW_LEN_KEYSTRING_BIT; DEBUG_INFO ("user pass change not supported with no keys.\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE); GPG_CONDITION_NOT_SATISFIED ();
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 ();
} }
else if (r > 0 && who == BY_USER) else if (r > 0 && who == BY_USER)
{ {
@@ -519,27 +513,14 @@ cmd_reset_user_password (void)
} }
else if (r < 0) else if (r < 0)
{ {
sec_fail:
DEBUG_INFO ("failed.\r\n"); DEBUG_INFO ("failed.\r\n");
gpg_pw_increment_err_counter (PW_ERR_RC); gpg_pw_increment_err_counter (PW_ERR_RC);
GPG_SECURITY_FAILURE (); GPG_SECURITY_FAILURE ();
} }
else if (r == 0) else if (r == 0)
{ {
if ((ks_rc[0] & PW_LEN_KEYSTRING_BIT) == 0 DEBUG_INFO ("user pass change not supported with no keys.\r\n");
|| memcmp (KS_GET_KEYSTRING (ks_rc), GPG_CONDITION_NOT_SATISFIED ();
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 ();
} }
else else
{ {
@@ -583,15 +564,8 @@ cmd_reset_user_password (void)
} }
else if (r == 0) else if (r == 0)
{ {
DEBUG_INFO ("done (no privkey).\r\n"); DEBUG_INFO ("user pass change not supported with no keys.\r\n");
new_ks0[0] |= PW_LEN_KEYSTRING_BIT; GPG_CONDITION_NOT_SATISFIED ();
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 ();
} }
else else
{ {