From e73ebbe33fc2945d3996e53249849aa41f36347b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 10 Oct 2013 13:46:18 +0900 Subject: [PATCH] Bug fix for flash ROM garbage collection --- ChangeLog | 6 ++++++ src/openpgp-do.c | 39 ++++++++++++++++++++++++--------------- src/openpgp.c | 10 +++++++--- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9976791..cb1968f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2013-10-10 Niibe Yutaka + * src/openpgp-do.c (gpg_do_write_prvkey): Two phase write to + work with garbage collection. + + * src/openpgp.c (cmd_change_password): Call gpg_do_write_simple + after accessing the data object (it may cause garbage collection). + * polarssl/library/bignum.c (mpi_montred): Constant time for carry propagation. Bug fix for carry propagation. (mpi_exp_mod): Bug fix. Shrink the size of RR as same as X. diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 1f111c1..a3a127c 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -890,37 +890,46 @@ 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. */ { - uint8_t ks_info[KS_META_SIZE]; + uint8_t ks_info0[KS_META_SIZE]; + uint8_t ks_info1[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; - 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); + ks_info0[0] = ks_pw1_len & PW_LEN_MASK; + memcpy (KS_GET_SALT (ks_info0), KS_GET_SALT (ks_pw1), SALT_SIZE); + ks_info0[KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE] = S2K_ITER; } if ((ks_rc_len & PW_LEN_KEYSTRING_BIT)) { - ks_rc_len &= PW_LEN_MASK; - 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); + ks_info1[0] = ks_rc_len & PW_LEN_MASK; + memcpy (KS_GET_SALT (ks_info1), KS_GET_SALT (ks_rc), SALT_SIZE); + ks_info1[KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE] = S2K_ITER; } + /* + * Note that gpg_do_write_simple may result garbage collection + * for flash ROM. Thus, it must be two phase. + */ + + 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); + if (keystring_admin) { const uint8_t *ks_admin = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); if (ks_admin != NULL) { - 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); + ks_info0[0] = ks_admin[0] & PW_LEN_MASK; + memcpy (KS_GET_SALT (ks_info0), KS_GET_SALT (ks_admin), + SALT_SIZE); + ks_info0[KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE] = S2K_ITER; + gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks_info0, KS_META_SIZE); } else { diff --git a/src/openpgp.c b/src/openpgp.c index 7702a0a..3917874 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -355,7 +355,6 @@ 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; } @@ -405,15 +404,20 @@ cmd_change_password (void) } else if (r > 0 && who == BY_ADMIN) { - if (!pw3_null) + if (pw3_null) + gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0); + else 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 (); } else /* r == 0 && who == BY_ADMIN */ /* no prvkey */ { - if (!pw3_null) + if (pw3_null) + gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0); + else { new_ks0[0] |= PW_LEN_KEYSTRING_BIT; gpg_do_write_simple (NR_DO_KEYSTRING_PW3, new_ks0, KEYSTRING_SIZE);