improve flash memory usage for passwd status and digital signature counter
This commit is contained in:
41
ChangeLog
41
ChangeLog
@@ -1,6 +1,45 @@
|
|||||||
|
2010-11-05 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/flash.c, src/gnuk.ld.in: Rename "Flash DO Pool" to "Flash
|
||||||
|
Data Pool", because it's not only DO.
|
||||||
|
* src/gnuk.h, src/opengpg-do.c: Cleanup.
|
||||||
|
|
||||||
|
Digital Signature Counter implementation improvement.
|
||||||
|
* src/gnuk.h (NR_DO_DS_COUNT): Removed.
|
||||||
|
(NR_COUNTER_DS, NR_COUNTER_DS_LSB): New.
|
||||||
|
* src/openpgp-do.c (do_ds_count_initial_value): Removed.
|
||||||
|
(gpg_do_increment_digital_signature_counter): Removed.
|
||||||
|
(digital_signature_counter): New variable.
|
||||||
|
(do_ds_count, gpg_increment_digital_signature_counter): New functions.
|
||||||
|
(gpg_do_table): Change the entry for GPG_DO_DS_COUNT as DO_PROC_READ.
|
||||||
|
(gpg_do_table_init): Handle digital_signature_counter.
|
||||||
|
* src/flash.c (flash_data_pool_allocate, flash_put_data): New.
|
||||||
|
|
||||||
|
Password status implementation improvement.
|
||||||
|
* src/gnuk.h (PW_STATUS_PW1, PW_STATUS_RC, PW_STATUS_PW3): Removed.
|
||||||
|
(PW_ERR_PW1, PW_ERR_RC, PW_ERR_PW3): New define.
|
||||||
|
(NR_COUNTER_123, NR_BOOL_PW1_LIFETIME): New define.
|
||||||
|
(NR_NONE, NR_EMPTY): New define.
|
||||||
|
* src/flash.c (flash_bool_clear, flash_bool_write)
|
||||||
|
(flash_cnt123_get_value, flash_cnt123_increment)
|
||||||
|
(flash_cnt123_clear): New functions.
|
||||||
|
* src/openpgp-do.c (do_pw_status_bytes_template): Removed.
|
||||||
|
(PW_STATUS_BYTES_TEMPLATE, gpg_do_reset_pw_counter): Removed.
|
||||||
|
(PASSWORD_ERRORS_MAX, PW_LEN_MAX): New define.
|
||||||
|
(pw1_lifetime_p, pw_err_counter_p): New variables.
|
||||||
|
(gpg_get_pw1_lifetime): New function.
|
||||||
|
(gpg_get_pw_err_counter, gpg_passwd_locked, gpg_reset_pw_counter)
|
||||||
|
(gpg_increment_pw_counter): New functions.
|
||||||
|
(rw_pw_status): Use pw1_lifetime_p and pw_err_counter_p.
|
||||||
|
(gpg_do_table_init): Handle NR_COUNTER_123 and NR_BOOL_PW1_LIFETIME.
|
||||||
|
* src/ac.c (verify_pso_cds, verify_pso_other, verify_admin_0):
|
||||||
|
Follow the changes.
|
||||||
|
* src/openpgp.c (cmd_change_password, cmd_reset_user_password)
|
||||||
|
(cmd_pso, cmd_internal_authenticate): Likewise.
|
||||||
|
|
||||||
2010-11-04 NIIBE Yutaka <gniibe@fsij.org>
|
2010-11-04 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
* src/flash.c (flash_warning): New.
|
* src/flash.c (flash_warning): New.
|
||||||
(flash_do_pool): Added header for DO pool.
|
(flash_do_pool): Added header for DO pool.
|
||||||
(flash_do_release): Fill zero.
|
(flash_do_release): Fill zero.
|
||||||
(flash_do_write): Change DO format in flash.
|
(flash_do_write): Change DO format in flash.
|
||||||
|
|||||||
52
src/ac.c
52
src/ac.c
@@ -56,16 +56,16 @@ ac_reset_pso_other (void)
|
|||||||
auth_status &= ~AC_PSO_OTHER_AUTHORIZED;
|
auth_status &= ~AC_PSO_OTHER_AUTHORIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify for "Perform Security Operation : Compute Digital Signature"
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
verify_pso_cds (const uint8_t *pw, int pw_len)
|
verify_pso_cds (const uint8_t *pw, int pw_len)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
|
||||||
uint8_t keystring[KEYSTRING_SIZE_PW1];
|
uint8_t keystring[KEYSTRING_SIZE_PW1];
|
||||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
|
||||||
|
|
||||||
if (pw_status_bytes == NULL
|
if (gpg_passwd_locked (PW_ERR_PW1))
|
||||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
DEBUG_INFO ("verify_pso_cds\r\n");
|
DEBUG_INFO ("verify_pso_cds\r\n");
|
||||||
@@ -73,18 +73,13 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
|
|||||||
|
|
||||||
keystring[0] = pw_len;
|
keystring[0] = pw_len;
|
||||||
sha1 (pw, pw_len, keystring+1);
|
sha1 (pw, pw_len, keystring+1);
|
||||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
|
||||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring+1)) < 0)
|
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring+1)) < 0)
|
||||||
{
|
{
|
||||||
pwsb[PW_STATUS_PW1]--;
|
gpg_increment_pw_err_counter (PW_ERR_PW1);
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
else if (pwsb[PW_STATUS_PW1] != 3)
|
else
|
||||||
{
|
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||||
pwsb[PW_STATUS_PW1] = 3;
|
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -93,20 +88,15 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
|
|||||||
int
|
int
|
||||||
verify_pso_other (const uint8_t *pw, int pw_len)
|
verify_pso_other (const uint8_t *pw, int pw_len)
|
||||||
{
|
{
|
||||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
|
||||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
|
||||||
const uint8_t *ks_pw1;
|
const uint8_t *ks_pw1;
|
||||||
|
|
||||||
DEBUG_INFO ("verify_pso_other\r\n");
|
DEBUG_INFO ("verify_pso_other\r\n");
|
||||||
|
|
||||||
if (pw_status_bytes == NULL
|
if (gpg_passwd_locked (PW_ERR_PW1))
|
||||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We check only the length of password string now.
|
* We check only the length of password string here.
|
||||||
* Real check is defered to decrypt/authenticate routines.
|
* Real check is defered to decrypt/authenticate routines.
|
||||||
*/
|
*/
|
||||||
ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||||
@@ -114,8 +104,8 @@ verify_pso_other (const uint8_t *pw, int pw_len)
|
|||||||
|| (ks_pw1 != NULL && pw_len == ks_pw1[0]))
|
|| (ks_pw1 != NULL && pw_len == ks_pw1[0]))
|
||||||
{ /* No problem */
|
{ /* No problem */
|
||||||
/*
|
/*
|
||||||
* We don't reset pwsb[PW_STATUS_PW1] here.
|
* We don't call gpg_reset_pw_err_counters here, because
|
||||||
* Because password may be wrong.
|
* password may be wrong.
|
||||||
*/
|
*/
|
||||||
pw1_keystring[0] = pw_len;
|
pw1_keystring[0] = pw_len;
|
||||||
sha1 (pw, pw_len, pw1_keystring+1);
|
sha1 (pw, pw_len, pw1_keystring+1);
|
||||||
@@ -124,8 +114,7 @@ verify_pso_other (const uint8_t *pw, int pw_len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pwsb[PW_STATUS_PW1]--;
|
gpg_increment_pw_err_counter (PW_ERR_PW1);
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,11 +161,9 @@ int
|
|||||||
verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
||||||
{
|
{
|
||||||
const uint8_t *pw3_keystring;
|
const uint8_t *pw3_keystring;
|
||||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
|
||||||
int pw_len;
|
int pw_len;
|
||||||
|
|
||||||
if (pw_status_bytes == NULL
|
if (gpg_passwd_locked (PW_ERR_PW3))
|
||||||
|| pw_status_bytes[PW_STATUS_PW3] == 0) /* locked */
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
|
pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
|
||||||
@@ -185,9 +172,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
|||||||
int count;
|
int count;
|
||||||
uint8_t md[KEYSTRING_MD_SIZE];
|
uint8_t md[KEYSTRING_MD_SIZE];
|
||||||
const uint8_t *salt;
|
const uint8_t *salt;
|
||||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
|
||||||
|
|
||||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
|
||||||
pw_len = pw3_keystring[0];
|
pw_len = pw3_keystring[0];
|
||||||
if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
|
if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
|
||||||
goto failure;
|
goto failure;
|
||||||
@@ -199,15 +184,12 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
|||||||
if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
|
if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
|
||||||
{
|
{
|
||||||
failure:
|
failure:
|
||||||
pwsb[PW_STATUS_PW3]--;
|
gpg_increment_pw_err_counter (PW_ERR_PW3);
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (pwsb[PW_STATUS_PW3] != 3)
|
else
|
||||||
{ /* OK, the user is now authenticated */
|
/* OK, the user is now authenticated */
|
||||||
pwsb[PW_STATUS_PW3] = 3;
|
gpg_reset_pw_err_counter (PW_ERR_PW3);
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* For empty PW3, pass phrase should be OPENPGP_CARD_INITIAL_PW3 */
|
/* For empty PW3, pass phrase should be OPENPGP_CARD_INITIAL_PW3 */
|
||||||
|
|||||||
193
src/flash.c
193
src/flash.c
@@ -24,8 +24,9 @@
|
|||||||
/*
|
/*
|
||||||
* We assume single DO size is less than 256.
|
* We assume single DO size is less than 256.
|
||||||
*
|
*
|
||||||
* NOTE: When we will support "Card holder certificate"
|
* NOTE: When we will support "Card holder certificate" (which size is
|
||||||
* (which size is larger than 256), it will not be put into DO pool.
|
* larger than 256), it will not be put into data pool, but will
|
||||||
|
* be implemented by its own flash page.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -128,15 +129,15 @@ flash_program_halfword (uint32_t addr, uint16_t data)
|
|||||||
*
|
*
|
||||||
* 1-KiB align padding
|
* 1-KiB align padding
|
||||||
*
|
*
|
||||||
* 1-KiB DO pool * 3
|
* 1-KiB data pool * 3
|
||||||
*
|
*
|
||||||
* 3-KiB Key store (512-byte (p, q and N) key-store * 6)
|
* 3-KiB Key store (512-byte (p, q and N) key-store * 6)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const uint8_t *do_pool;
|
static const uint8_t *data_pool;
|
||||||
static const uint8_t *keystore_pool;
|
static const uint8_t *keystore_pool;
|
||||||
|
|
||||||
static const uint8_t *last_p;
|
static uint8_t *last_p;
|
||||||
static const uint8_t *keystore;
|
static const uint8_t *keystore;
|
||||||
|
|
||||||
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
||||||
@@ -144,7 +145,7 @@ const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Linker set this symbol */
|
/* Linker set this symbol */
|
||||||
extern uint8_t _do_pool;
|
extern uint8_t _data_pool;
|
||||||
|
|
||||||
void
|
void
|
||||||
flash_init (void)
|
flash_init (void)
|
||||||
@@ -152,7 +153,7 @@ flash_init (void)
|
|||||||
const uint8_t *p;
|
const uint8_t *p;
|
||||||
extern uint8_t _keystore_pool;
|
extern uint8_t _keystore_pool;
|
||||||
|
|
||||||
do_pool = &_do_pool;
|
data_pool = &_data_pool;
|
||||||
keystore_pool = &_keystore_pool;
|
keystore_pool = &_keystore_pool;
|
||||||
|
|
||||||
/* Seek empty keystore */
|
/* Seek empty keystore */
|
||||||
@@ -166,48 +167,74 @@ flash_init (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DO pool managenent
|
* Flash data pool managenent
|
||||||
*
|
*
|
||||||
* DO pool consists of two part:
|
* Flash data pool consists of two parts:
|
||||||
* 2-byte header
|
* 2-byte header
|
||||||
* contents
|
* contents
|
||||||
*
|
*
|
||||||
* Format of a DO pool content:
|
* Flash data pool objects:
|
||||||
|
* Data Object (DO) (of smart card)
|
||||||
|
* Internal objects:
|
||||||
|
* NONE (0x0000)
|
||||||
|
* 123-counter
|
||||||
|
* 14-bit counter
|
||||||
|
* bool object
|
||||||
|
*
|
||||||
|
* Format of a Data Object:
|
||||||
* NR: 8-bit tag_number
|
* NR: 8-bit tag_number
|
||||||
* LEN: 8-bit length
|
* LEN: 8-bit length
|
||||||
* DATA: data * LEN
|
* DATA: data * LEN
|
||||||
* PAD: optional byte for 16-bit alignment
|
* PAD: optional byte for 16-bit alignment
|
||||||
*/
|
*/
|
||||||
#define FLASH_DO_POOL_HEADER_SIZE 2
|
#define FLASH_DATA_POOL_HEADER_SIZE 2
|
||||||
#define FLASH_DO_POOL_SIZE 1024*3
|
#define FLASH_DATA_POOL_SIZE (1024*3)
|
||||||
#define FLASH_PAGE_SIZE 1024
|
#define FLASH_PAGE_SIZE 1024
|
||||||
|
|
||||||
const uint8_t *
|
const uint8_t *
|
||||||
flash_do_pool (void)
|
flash_data_pool (void)
|
||||||
{
|
{
|
||||||
return do_pool + FLASH_DO_POOL_HEADER_SIZE;
|
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
flash_set_do_pool_last (const uint8_t *p)
|
flash_set_data_pool_last (const uint8_t *p)
|
||||||
{
|
{
|
||||||
last_p = p;
|
last_p = (uint8_t *)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t *
|
||||||
|
flash_data_pool_allocate (size_t size)
|
||||||
|
{
|
||||||
|
uint8_t *p = last_p;
|
||||||
|
|
||||||
|
size = (size + 1) & ~1; /* allocation unit is 1-word (2-byte) */
|
||||||
|
|
||||||
|
if (last_p + size > data_pool - FLASH_DATA_POOL_HEADER_SIZE + FLASH_PAGE_SIZE)
|
||||||
|
return NULL; /* gc/erase/.../ */
|
||||||
|
|
||||||
|
last_p += size;
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *
|
const uint8_t *
|
||||||
flash_do_write (uint8_t nr, const uint8_t *data, int len)
|
flash_do_write (uint8_t nr, const uint8_t *data, int len)
|
||||||
{
|
{
|
||||||
const uint8_t *p = last_p;
|
const uint8_t *p;
|
||||||
uint16_t hw;
|
uint16_t hw;
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (last_p - do_pool + len + FLASH_DO_POOL_HEADER_SIZE + 2 > FLASH_PAGE_SIZE)
|
|
||||||
return NULL; /* gc/erase/.../ */
|
|
||||||
|
|
||||||
DEBUG_INFO ("flash DO\r\n");
|
DEBUG_INFO ("flash DO\r\n");
|
||||||
|
|
||||||
addr = (uint32_t)last_p;
|
p = flash_data_pool_allocate (2 + len);
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
DEBUG_INFO ("flash data pool allocation failure.\r\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = (uint32_t)p;
|
||||||
hw = nr | (len << 8);
|
hw = nr | (len << 8);
|
||||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -229,8 +256,6 @@ flash_do_write (uint8_t nr, const uint8_t *data, int len)
|
|||||||
addr += 2;
|
addr += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_p = (const uint8_t *)addr;
|
|
||||||
|
|
||||||
DEBUG_INFO ("flash DO...done\r\n");
|
DEBUG_INFO ("flash DO...done\r\n");
|
||||||
return p + 1;
|
return p + 1;
|
||||||
}
|
}
|
||||||
@@ -253,7 +278,7 @@ flash_do_release (const uint8_t *do_data)
|
|||||||
int len = do_data[0];
|
int len = do_data[0];
|
||||||
|
|
||||||
/* Don't filling zero for data in code (such as ds_count_initial_value) */
|
/* Don't filling zero for data in code (such as ds_count_initial_value) */
|
||||||
if (do_data < &_do_pool || do_data > &_do_pool + FLASH_DO_POOL_SIZE)
|
if (do_data < &_data_pool || do_data > &_data_pool + FLASH_DATA_POOL_SIZE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
addr += 2;
|
addr += 2;
|
||||||
@@ -327,3 +352,121 @@ flash_clear_halfword (uint32_t addr)
|
|||||||
flash_program_halfword (addr, 0);
|
flash_program_halfword (addr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
flash_put_data (uint16_t hw)
|
||||||
|
{
|
||||||
|
uint8_t *p;
|
||||||
|
|
||||||
|
p = flash_data_pool_allocate (2);
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
DEBUG_INFO ("data allocation failure.\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
flash_program_halfword ((uint32_t)p, hw);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
flash_bool_clear (const uint8_t **addr_p)
|
||||||
|
{
|
||||||
|
const uint8_t *p;
|
||||||
|
|
||||||
|
if ((p = *addr_p) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
flash_program_halfword ((uint32_t)p, 0);
|
||||||
|
*addr_p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *
|
||||||
|
flash_bool_write (uint8_t nr)
|
||||||
|
{
|
||||||
|
uint8_t *p;
|
||||||
|
uint16_t hw = nr;
|
||||||
|
|
||||||
|
p = flash_data_pool_allocate (2);
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
DEBUG_INFO ("bool allocation failure.\r\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
flash_program_halfword ((uint32_t)p, hw);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
flash_cnt123_get_value (const uint8_t *p)
|
||||||
|
{
|
||||||
|
if (p == NULL)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t v = *p;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* After erase, a word in flash memory becomes 0xffff.
|
||||||
|
* The word can be programmed to any value.
|
||||||
|
* Then, the word can be programmed to zero.
|
||||||
|
*
|
||||||
|
* Thus, we can represent value 1, 2, and 3.
|
||||||
|
*/
|
||||||
|
if (v == 0xff)
|
||||||
|
return 1;
|
||||||
|
else if (v == 0x00)
|
||||||
|
return 3;
|
||||||
|
else
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
flash_cnt123_increment (uint8_t which, const uint8_t **addr_p)
|
||||||
|
{
|
||||||
|
const uint8_t *p;
|
||||||
|
uint16_t hw;
|
||||||
|
|
||||||
|
if ((p = *addr_p) == NULL)
|
||||||
|
{
|
||||||
|
p = flash_data_pool_allocate (4);
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
DEBUG_INFO ("cnt123 allocation failure.\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hw = NR_COUNTER_123 | (which << 8);
|
||||||
|
flash_program_halfword ((uint32_t)p, hw);
|
||||||
|
*addr_p = p + 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t v = *p;
|
||||||
|
|
||||||
|
if (v == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (v == 0xff)
|
||||||
|
hw = 0xc3c3;
|
||||||
|
else
|
||||||
|
hw = 0;
|
||||||
|
|
||||||
|
flash_program_halfword ((uint32_t)p, hw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
flash_cnt123_clear (const uint8_t **addr_p)
|
||||||
|
{
|
||||||
|
const uint8_t *p;
|
||||||
|
|
||||||
|
if ((p = *addr_p) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
flash_program_halfword ((uint32_t)p, 0);
|
||||||
|
p -= 2;
|
||||||
|
flash_program_halfword ((uint32_t)p, 0);
|
||||||
|
*addr_p = NULL;
|
||||||
|
}
|
||||||
|
|||||||
127
src/gnuk.h
127
src/gnuk.h
@@ -51,6 +51,13 @@ extern int res_APDU_size;
|
|||||||
#define AC_NEVER 0x80
|
#define AC_NEVER 0x80
|
||||||
#define AC_ALWAYS 0xFF
|
#define AC_ALWAYS 0xFF
|
||||||
|
|
||||||
|
#define PW_ERR_PW1 0
|
||||||
|
#define PW_ERR_RC 1
|
||||||
|
#define PW_ERR_PW3 2
|
||||||
|
extern int gpg_passwd_locked (uint8_t which);
|
||||||
|
extern void gpg_reset_pw_err_counter (uint8_t which);
|
||||||
|
extern void gpg_increment_pw_err_counter (uint8_t which);
|
||||||
|
|
||||||
extern int ac_check_status (uint8_t ac_flag);
|
extern int ac_check_status (uint8_t ac_flag);
|
||||||
extern int verify_pso_cds (const uint8_t *pw, int pw_len);
|
extern int verify_pso_cds (const uint8_t *pw, int pw_len);
|
||||||
extern int verify_pso_other (const uint8_t *pw, int pw_len);
|
extern int verify_pso_other (const uint8_t *pw, int pw_len);
|
||||||
@@ -63,7 +70,6 @@ extern void ac_reset_pso_other (void);
|
|||||||
|
|
||||||
extern void write_res_apdu (const uint8_t *p, int len,
|
extern void write_res_apdu (const uint8_t *p, int len,
|
||||||
uint8_t sw1, uint8_t sw2);
|
uint8_t sw1, uint8_t sw2);
|
||||||
|
|
||||||
uint16_t data_objects_number_of_bytes;
|
uint16_t data_objects_number_of_bytes;
|
||||||
|
|
||||||
extern int gpg_do_table_init (void);
|
extern int gpg_do_table_init (void);
|
||||||
@@ -84,9 +90,11 @@ extern void flash_do_release (const uint8_t *);
|
|||||||
extern const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
|
extern const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
|
||||||
extern uint8_t *flash_key_alloc (void);
|
extern uint8_t *flash_key_alloc (void);
|
||||||
extern void flash_key_release (const uint8_t *);
|
extern void flash_key_release (const uint8_t *);
|
||||||
extern const uint8_t *flash_do_pool (void);
|
extern const uint8_t *flash_data_pool (void);
|
||||||
extern void flash_set_do_pool_last (const uint8_t *p);
|
extern void flash_set_data_pool_last (const uint8_t *p);
|
||||||
extern void flash_clear_halfword (uint32_t addr);
|
extern void flash_clear_halfword (uint32_t addr);
|
||||||
|
extern void flash_increment_counter (uint8_t counter_tag_nr);
|
||||||
|
extern void flash_reset_counter (uint8_t counter_tag_nr);
|
||||||
|
|
||||||
#define KEY_MAGIC_LEN 8
|
#define KEY_MAGIC_LEN 8
|
||||||
#define KEY_CONTENT_LEN 256 /* p and q */
|
#define KEY_CONTENT_LEN 256 /* p and q */
|
||||||
@@ -165,11 +173,7 @@ extern int gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, in
|
|||||||
|
|
||||||
extern const uint8_t *gpg_do_read_simple (uint8_t);
|
extern const uint8_t *gpg_do_read_simple (uint8_t);
|
||||||
extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
|
extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
|
||||||
extern void gpg_do_increment_digital_signature_counter (void);
|
extern void gpg_increment_digital_signature_counter (void);
|
||||||
|
|
||||||
#define PW_STATUS_PW1 4
|
|
||||||
#define PW_STATUS_RC 5
|
|
||||||
#define PW_STATUS_PW3 6
|
|
||||||
|
|
||||||
|
|
||||||
extern void gpg_set_pw3 (const uint8_t *newpw, int newpw_len);
|
extern void gpg_set_pw3 (const uint8_t *newpw, int newpw_len);
|
||||||
@@ -177,30 +181,76 @@ extern void fatal (void) __attribute__ ((noreturn));
|
|||||||
|
|
||||||
extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||||
|
|
||||||
#define NR_DO_PRVKEY_SIG 0
|
/*** Flash memory tag values ***/
|
||||||
#define NR_DO_PRVKEY_DEC 1
|
#define NR_NONE 0x00
|
||||||
#define NR_DO_PRVKEY_AUT 2
|
/* Data objects */
|
||||||
#define NR_DO_KEYSTRING_PW1 3
|
/*
|
||||||
#define NR_DO_KEYSTRING_RC 4
|
* Representation of data object:
|
||||||
#define NR_DO_KEYSTRING_PW3 5
|
*
|
||||||
#define NR_DO_PW_STATUS 6
|
* <-1 word-> <--len/2 words->
|
||||||
#define NR_DO_DS_COUNT 7
|
* <tag><len> <-data content->
|
||||||
#define NR_DO_SEX 8
|
*/
|
||||||
#define NR_DO_FP_SIG 9
|
#define NR_DO__FIRST__ 0x01
|
||||||
#define NR_DO_FP_DEC 10
|
#define NR_DO_SEX 0x01
|
||||||
#define NR_DO_FP_AUT 11
|
#define NR_DO_FP_SIG 0x02
|
||||||
#define NR_DO_CAFP_1 12
|
#define NR_DO_FP_DEC 0x03
|
||||||
#define NR_DO_CAFP_2 13
|
#define NR_DO_FP_AUT 0x04
|
||||||
#define NR_DO_CAFP_3 14
|
#define NR_DO_CAFP_1 0x05
|
||||||
#define NR_DO_KGTIME_SIG 15
|
#define NR_DO_CAFP_2 0x06
|
||||||
#define NR_DO_KGTIME_DEC 16
|
#define NR_DO_CAFP_3 0x07
|
||||||
#define NR_DO_KGTIME_AUT 17
|
#define NR_DO_KGTIME_SIG 0x08
|
||||||
#define NR_DO_LOGIN_DATA 18
|
#define NR_DO_KGTIME_DEC 0x09
|
||||||
#define NR_DO_URL 19
|
#define NR_DO_KGTIME_AUT 0x0a
|
||||||
#define NR_DO_NAME 20
|
#define NR_DO_LOGIN_DATA 0x0b
|
||||||
#define NR_DO_LANGUAGE 21
|
#define NR_DO_URL 0x0c
|
||||||
#define NR_DO_CH_CERTIFICATE 22
|
#define NR_DO_NAME 0x0d
|
||||||
#define NR_DO_LAST 23
|
#define NR_DO_LANGUAGE 0x0e
|
||||||
|
#define NR_DO_PRVKEY_SIG 0x0f
|
||||||
|
#define NR_DO_PRVKEY_DEC 0x10
|
||||||
|
#define NR_DO_PRVKEY_AUT 0x11
|
||||||
|
#define NR_DO_KEYSTRING_PW1 0x12
|
||||||
|
#define NR_DO_KEYSTRING_RC 0x13
|
||||||
|
#define NR_DO_KEYSTRING_PW3 0x14
|
||||||
|
#define NR_DO__LAST__ 21 /* == 0x15 */
|
||||||
|
/* 14-bit counter for DS: Recorded in flash memory by 1-word (2-byte). */
|
||||||
|
/*
|
||||||
|
* Representation of 14-bit counter:
|
||||||
|
* 0: 0x8000
|
||||||
|
* 1: 0x8001
|
||||||
|
* ...
|
||||||
|
* 16383: 0xbfff
|
||||||
|
*/
|
||||||
|
#define NR_COUNTER_DS 0x80 /* ..0xbf */
|
||||||
|
/* 10-bit counter for DS: Recorded in flash memory by 1-word (2-byte). */
|
||||||
|
/*
|
||||||
|
* Representation of 10-bit counter:
|
||||||
|
* 0: 0xc000
|
||||||
|
* 1: 0xc001
|
||||||
|
* ...
|
||||||
|
* 1023: 0xc3ff
|
||||||
|
*/
|
||||||
|
#define NR_COUNTER_DS_LSB 0xc0 /* ..0xc3 */
|
||||||
|
/* 8-bit int or Boolean objects: Recorded in flash memory by 1-word (2-byte) */
|
||||||
|
/*
|
||||||
|
* Representation of Boolean object:
|
||||||
|
* 0: No record in flash memory
|
||||||
|
* 1: 0xc?00
|
||||||
|
*/
|
||||||
|
#define NR_BOOL_PW1_LIFETIME 0xf0
|
||||||
|
/*
|
||||||
|
* NR_BOOL_SOMETHING, NR_UINT_SOMETHING could be here... Use 0xf?
|
||||||
|
*/
|
||||||
|
/* 123-counters: Recorded in flash memory by 2-word (4-byte). */
|
||||||
|
/*
|
||||||
|
* Representation of 123-counters:
|
||||||
|
* 0: No record in flash memory
|
||||||
|
* 1: 0xfe?? 0xffff
|
||||||
|
* 2: 0xfe?? 0xc3c3
|
||||||
|
* 3: 0xfe?? 0x0000
|
||||||
|
* where <counter_id> is placed at second byte <??>
|
||||||
|
*/
|
||||||
|
#define NR_COUNTER_123 0xfe
|
||||||
|
#define NR_EMPTY 0xff
|
||||||
|
|
||||||
#define SIZE_PW_STATUS_BYTES 7
|
#define SIZE_PW_STATUS_BYTES 7
|
||||||
|
|
||||||
@@ -211,8 +261,6 @@ extern void random_bytes_free (const uint8_t *);
|
|||||||
|
|
||||||
extern uint32_t hardclock (void);
|
extern uint32_t hardclock (void);
|
||||||
|
|
||||||
extern void gpg_do_reset_pw_counter (uint8_t which);
|
|
||||||
|
|
||||||
extern void set_led (int);
|
extern void set_led (int);
|
||||||
|
|
||||||
#define NUM_ALL_PRV_KEYS 3 /* SIG, DEC and AUT */
|
#define NUM_ALL_PRV_KEYS 3 /* SIG, DEC and AUT */
|
||||||
@@ -227,4 +275,13 @@ extern uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
|
|||||||
#define OPENPGP_CARD_INITIAL_PW3 "12345678"
|
#define OPENPGP_CARD_INITIAL_PW3 "12345678"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const uint8_t openpgpcard_aid[17] __attribute__ ((aligned (1)));
|
extern const uint8_t openpgpcard_aid[17] __attribute__ ((aligned (1)));
|
||||||
|
|
||||||
|
extern int gpg_get_pw1_lifetime (void);
|
||||||
|
|
||||||
|
extern void flash_bool_clear (const uint8_t **addr_p);
|
||||||
|
extern const uint8_t *flash_bool_write (uint8_t nr);
|
||||||
|
extern int flash_cnt123_get_value (const uint8_t *p);
|
||||||
|
extern void flash_cnt123_increment (uint8_t which, const uint8_t **addr_p);
|
||||||
|
extern void flash_cnt123_clear (const uint8_t **addr_p);
|
||||||
|
extern void flash_put_data (uint16_t hw);
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ SECTIONS
|
|||||||
|
|
||||||
.gnuk_flash : ALIGN (1024)
|
.gnuk_flash : ALIGN (1024)
|
||||||
{
|
{
|
||||||
_do_pool = .;
|
_data_pool = .;
|
||||||
KEEP(*(.gnuk_data))
|
KEEP(*(.gnuk_data))
|
||||||
FILL(0xffffffff);
|
FILL(0xffffffff);
|
||||||
. = ALIGN(1024);
|
. = ALIGN(1024);
|
||||||
|
|||||||
418
src/openpgp-do.c
418
src/openpgp-do.c
@@ -32,6 +32,67 @@
|
|||||||
#include "polarssl/aes.h"
|
#include "polarssl/aes.h"
|
||||||
#include "polarssl/sha1.h"
|
#include "polarssl/sha1.h"
|
||||||
|
|
||||||
|
static uint32_t digital_signature_counter;
|
||||||
|
|
||||||
|
void
|
||||||
|
gpg_increment_digital_signature_counter (void)
|
||||||
|
{
|
||||||
|
uint16_t hw0, hw1;
|
||||||
|
|
||||||
|
digital_signature_counter++;
|
||||||
|
digital_signature_counter &= 0x00ffffff;
|
||||||
|
|
||||||
|
if ((digital_signature_counter & 0x03ff) == 0)
|
||||||
|
{ /* carry occurs from l10 to h14 */
|
||||||
|
hw0 = NR_COUNTER_DS
|
||||||
|
| ((digital_signature_counter & 0x00fc0000) >> 18)
|
||||||
|
| ((digital_signature_counter & 0x0003fc00) >> 2);
|
||||||
|
hw1 = NR_COUNTER_DS_LSB;
|
||||||
|
flash_put_data (hw0);
|
||||||
|
flash_put_data (hw1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hw1 = NR_COUNTER_DS_LSB
|
||||||
|
| ((digital_signature_counter & 0x0300) >> 8)
|
||||||
|
| ((digital_signature_counter & 0x00ff) << 8);
|
||||||
|
flash_put_data (hw1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */
|
||||||
|
const uint8_t *pw_err_counter_p[3];
|
||||||
|
|
||||||
|
static int
|
||||||
|
gpg_get_pw_err_counter (uint8_t which)
|
||||||
|
{
|
||||||
|
return flash_cnt123_get_value (pw_err_counter_p[which]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
gpg_passwd_locked (uint8_t which)
|
||||||
|
{
|
||||||
|
if (gpg_get_pw_err_counter (which) >= PASSWORD_ERRORS_MAX)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gpg_reset_pw_err_counter (uint8_t which)
|
||||||
|
{
|
||||||
|
flash_cnt123_clear (&pw_err_counter_p[which]);
|
||||||
|
if (pw_err_counter_p[which] != NULL)
|
||||||
|
GPG_MEMORY_FAILURE ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gpg_increment_pw_err_counter (uint8_t which)
|
||||||
|
{
|
||||||
|
flash_cnt123_increment (which, &pw_err_counter_p[which]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t data_objects_number_of_bytes;
|
uint16_t data_objects_number_of_bytes;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -89,21 +150,24 @@ static const uint8_t algorithm_attr[] __attribute__ ((aligned (1))) = {
|
|||||||
0x00 /* 0: p&q , 3: CRT with N (not yet supported) */
|
0x00 /* 0: p&q , 3: CRT with N (not yet supported) */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t do_ds_count_initial_value[] __attribute__ ((aligned (1))) = {
|
#define PW_LEN_MAX 127
|
||||||
3,
|
/*
|
||||||
0, 0, 0
|
* Representation of PW1_LIFETIME:
|
||||||
};
|
* 0: PW1_LIEFTIME_P == NULL : PW1 is valid for single PSO:CDS command
|
||||||
|
* 1: PW1_LIEFTIME_P != NULL : PW1 is valid for several PSO:CDS commands
|
||||||
static const uint8_t do_pw_status_bytes_template[] __attribute__ ((aligned (1))) = {
|
*
|
||||||
7,
|
* The address in the variable PW1_LIEFTIME_P is used when filling zero
|
||||||
0, /* PW1 is valid for single PSO:CDS command */
|
* in flash memory
|
||||||
127, 127, 127, /* max length of PW1, RC, and PW3 */
|
*/
|
||||||
3, 0, 3 /* Error counter of PW1, RC, and PW3 */
|
static const uint8_t *pw1_lifetime_p;
|
||||||
};
|
int
|
||||||
#define PW_STATUS_BYTES_TEMPLATE (do_pw_status_bytes_template+1)
|
gpg_get_pw1_lifetime (void)
|
||||||
|
{
|
||||||
#define SIZE_DIGITAL_SIGNATURE_COUNTER 3
|
if (pw1_lifetime_p == NULL)
|
||||||
/* 3-byte binary (big endian) */
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define SIZE_FINGER_PRINT 20
|
#define SIZE_FINGER_PRINT 20
|
||||||
#define SIZE_KEYGEN_TIME 4 /* RFC4880 */
|
#define SIZE_KEYGEN_TIME 4 /* RFC4880 */
|
||||||
@@ -130,13 +194,6 @@ static uint8_t *res_p;
|
|||||||
static void copy_do_1 (uint16_t tag, const uint8_t *do_data, int with_tag);
|
static void copy_do_1 (uint16_t tag, const uint8_t *do_data, int with_tag);
|
||||||
static const struct do_table_entry *get_do_entry (uint16_t tag);
|
static const struct do_table_entry *get_do_entry (uint16_t tag);
|
||||||
|
|
||||||
#define GNUK_DO_PRVKEY_SIG 0xff01
|
|
||||||
#define GNUK_DO_PRVKEY_DEC 0xff02
|
|
||||||
#define GNUK_DO_PRVKEY_AUT 0xff03
|
|
||||||
#define GNUK_DO_KEYSTRING_PW1 0xff04
|
|
||||||
#define GNUK_DO_KEYSTRING_RC 0xff05
|
|
||||||
#define GNUK_DO_KEYSTRING_PW3 0xff06
|
|
||||||
#define GNUK_DO_PW_STATUS 0xff07
|
|
||||||
#define GPG_DO_AID 0x004f
|
#define GPG_DO_AID 0x004f
|
||||||
#define GPG_DO_NAME 0x005b
|
#define GPG_DO_NAME 0x005b
|
||||||
#define GPG_DO_LOGIN_DATA 0x005e
|
#define GPG_DO_LOGIN_DATA 0x005e
|
||||||
@@ -170,30 +227,13 @@ static const struct do_table_entry *get_do_entry (uint16_t tag);
|
|||||||
#define GPG_DO_HIST_BYTES 0x5f52
|
#define GPG_DO_HIST_BYTES 0x5f52
|
||||||
#define GPG_DO_CH_CERTIFICATE 0x7f21
|
#define GPG_DO_CH_CERTIFICATE 0x7f21
|
||||||
|
|
||||||
#define NUM_DO_OBJS 23
|
static const uint8_t *do_ptr[NR_DO__LAST__];
|
||||||
static const uint8_t *do_ptr[NUM_DO_OBJS];
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
do_tag_to_nr (uint16_t tag)
|
do_tag_to_nr (uint16_t tag)
|
||||||
{
|
{
|
||||||
switch (tag)
|
switch (tag)
|
||||||
{
|
{
|
||||||
case GNUK_DO_PRVKEY_SIG:
|
|
||||||
return NR_DO_PRVKEY_SIG;
|
|
||||||
case GNUK_DO_PRVKEY_DEC:
|
|
||||||
return NR_DO_PRVKEY_DEC;
|
|
||||||
case GNUK_DO_PRVKEY_AUT:
|
|
||||||
return NR_DO_PRVKEY_AUT;
|
|
||||||
case GNUK_DO_KEYSTRING_PW1:
|
|
||||||
return NR_DO_KEYSTRING_PW1;
|
|
||||||
case GNUK_DO_KEYSTRING_RC:
|
|
||||||
return NR_DO_KEYSTRING_RC;
|
|
||||||
case GNUK_DO_KEYSTRING_PW3:
|
|
||||||
return NR_DO_KEYSTRING_PW3;
|
|
||||||
case GNUK_DO_PW_STATUS:
|
|
||||||
return NR_DO_PW_STATUS;
|
|
||||||
case GPG_DO_DS_COUNT:
|
|
||||||
return NR_DO_DS_COUNT;
|
|
||||||
case GPG_DO_SEX:
|
case GPG_DO_SEX:
|
||||||
return NR_DO_SEX;
|
return NR_DO_SEX;
|
||||||
case GPG_DO_FP_SIG:
|
case GPG_DO_FP_SIG:
|
||||||
@@ -222,8 +262,6 @@ do_tag_to_nr (uint16_t tag)
|
|||||||
return NR_DO_NAME;
|
return NR_DO_NAME;
|
||||||
case GPG_DO_LANGUAGE:
|
case GPG_DO_LANGUAGE:
|
||||||
return NR_DO_LANGUAGE;
|
return NR_DO_LANGUAGE;
|
||||||
case GPG_DO_CH_CERTIFICATE:
|
|
||||||
return NR_DO_CH_CERTIFICATE;
|
|
||||||
default:
|
default:
|
||||||
fatal ();
|
fatal ();
|
||||||
}
|
}
|
||||||
@@ -357,51 +395,65 @@ do_kgtime_all (uint16_t tag, int with_tag)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_ds_count (uint16_t tag, int with_tag)
|
||||||
|
{
|
||||||
|
if (with_tag)
|
||||||
|
{
|
||||||
|
copy_tag (tag);
|
||||||
|
*res_p++ = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
*res_p++ = (digital_signature_counter >> 16) & 0xff;
|
||||||
|
*res_p++ = (digital_signature_counter >> 8) & 0xff;
|
||||||
|
*res_p++ = digital_signature_counter & 0xff;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rw_pw_status (uint16_t tag, int with_tag,
|
rw_pw_status (uint16_t tag, int with_tag,
|
||||||
const uint8_t *data, int len, int is_write)
|
const uint8_t *data, int len, int is_write)
|
||||||
{
|
{
|
||||||
const uint8_t *do_data = do_ptr[NR_DO_PW_STATUS];
|
|
||||||
|
|
||||||
if (is_write)
|
if (is_write)
|
||||||
{
|
{
|
||||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
(void)len; /* Should be SIZE_PW_STATUS_BYTES */
|
||||||
|
|
||||||
(void)len;
|
/* Only the first byte of DATA is checked */
|
||||||
if (do_data)
|
if (data[0] == 0)
|
||||||
{
|
{
|
||||||
memcpy (pwsb, &do_data[1], SIZE_PW_STATUS_BYTES);
|
flash_bool_clear (&pw1_lifetime_p);
|
||||||
flash_do_release (do_data);
|
if (pw1_lifetime_p == NULL)
|
||||||
|
GPG_SUCCESS ();
|
||||||
|
else
|
||||||
|
GPG_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy (pwsb, PW_STATUS_BYTES_TEMPLATE, SIZE_PW_STATUS_BYTES);
|
{
|
||||||
|
pw1_lifetime_p = flash_bool_write (NR_BOOL_PW1_LIFETIME);
|
||||||
pwsb[0] = data[0];
|
if (pw1_lifetime_p != NULL)
|
||||||
do_ptr[NR_DO_PW_STATUS]
|
GPG_SUCCESS ();
|
||||||
= flash_do_write (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
else
|
||||||
if (do_ptr[NR_DO_PW_STATUS])
|
GPG_MEMORY_FAILURE();
|
||||||
GPG_SUCCESS ();
|
}
|
||||||
else
|
|
||||||
GPG_MEMORY_FAILURE();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (do_data)
|
if (with_tag)
|
||||||
{
|
{
|
||||||
if (with_tag)
|
copy_tag (tag);
|
||||||
{
|
*res_p++ = SIZE_PW_STATUS_BYTES;
|
||||||
copy_tag (tag);
|
|
||||||
*res_p++ = SIZE_PW_STATUS_BYTES;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (res_p, &do_data[1], SIZE_PW_STATUS_BYTES);
|
|
||||||
res_p += SIZE_PW_STATUS_BYTES;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return 0;
|
*res_p++ = gpg_get_pw1_lifetime ();
|
||||||
|
*res_p++ = PW_LEN_MAX;
|
||||||
|
*res_p++ = PW_LEN_MAX;
|
||||||
|
*res_p++ = PW_LEN_MAX;
|
||||||
|
*res_p++ = PASSWORD_ERRORS_MAX - gpg_get_pw_err_counter (PW_ERR_PW1);
|
||||||
|
*res_p++ = PASSWORD_ERRORS_MAX - gpg_get_pw_err_counter (PW_ERR_RC);
|
||||||
|
*res_p++ = PASSWORD_ERRORS_MAX - gpg_get_pw_err_counter (PW_ERR_PW3);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,8 +498,7 @@ proc_resetting_code (const uint8_t *data, int len)
|
|||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset RC counter in GNUK_DO_PW_STATUS */
|
gpg_reset_pw_err_counter (PW_ERR_RC);
|
||||||
gpg_do_reset_pw_counter (PW_STATUS_RC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -508,7 +559,7 @@ int
|
|||||||
gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
||||||
{
|
{
|
||||||
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
||||||
const uint8_t *do_data = do_ptr[nr];
|
const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__];
|
||||||
uint8_t *key_addr;
|
uint8_t *key_addr;
|
||||||
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
||||||
|
|
||||||
@@ -557,7 +608,7 @@ 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;
|
const uint8_t *dek;
|
||||||
const uint8_t *do_data = do_ptr[nr];
|
const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__];
|
||||||
const uint8_t *ks_pw1;
|
const uint8_t *ks_pw1;
|
||||||
const uint8_t *ks_rc;
|
const uint8_t *ks_rc;
|
||||||
|
|
||||||
@@ -659,7 +710,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
|
encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
|
||||||
|
|
||||||
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] = p;
|
do_ptr[nr - NR_DO__FIRST__] = p;
|
||||||
|
|
||||||
if (do_data == NULL)
|
if (do_data == NULL)
|
||||||
random_bytes_free (dek);
|
random_bytes_free (dek);
|
||||||
@@ -693,7 +744,7 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
|
|||||||
int who_new, const uint8_t *new_ks)
|
int who_new, const uint8_t *new_ks)
|
||||||
{
|
{
|
||||||
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
||||||
const uint8_t *do_data = do_ptr[nr];
|
const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__];
|
||||||
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
||||||
struct prvkey_data *pd;
|
struct prvkey_data *pd;
|
||||||
const uint8_t *p;
|
const uint8_t *p;
|
||||||
@@ -715,7 +766,7 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
|
|||||||
memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE);
|
memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||||
|
|
||||||
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] = p;
|
do_ptr[nr - NR_DO__FIRST__] = p;
|
||||||
|
|
||||||
flash_do_release (do_data);
|
flash_do_release (do_data);
|
||||||
free (pd);
|
free (pd);
|
||||||
@@ -752,7 +803,7 @@ proc_key_import (const uint8_t *data, int len)
|
|||||||
if (len <= 22)
|
if (len <= 22)
|
||||||
{ /* Deletion of the key */
|
{ /* Deletion of the key */
|
||||||
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
||||||
const uint8_t *do_data = do_ptr[nr];
|
const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__];
|
||||||
|
|
||||||
/* Delete the key */
|
/* Delete the key */
|
||||||
if (do_data)
|
if (do_data)
|
||||||
@@ -762,7 +813,7 @@ proc_key_import (const uint8_t *data, int len)
|
|||||||
flash_key_release (key_addr);
|
flash_key_release (key_addr);
|
||||||
flash_do_release (do_data);
|
flash_do_release (do_data);
|
||||||
}
|
}
|
||||||
do_ptr[nr] = NULL;
|
do_ptr[nr - NR_DO__FIRST__] = NULL;
|
||||||
|
|
||||||
if (--num_prv_keys == 0)
|
if (--num_prv_keys == 0)
|
||||||
{
|
{
|
||||||
@@ -779,7 +830,7 @@ proc_key_import (const uint8_t *data, int len)
|
|||||||
/* Skip E, 4-byte */
|
/* 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_md_pw3);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
GPG_MEMORY_FAILURE();
|
GPG_MEMORY_FAILURE ();
|
||||||
else
|
else
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
}
|
}
|
||||||
@@ -806,38 +857,29 @@ static const uint16_t const cmp_ss_temp[] = { 1, GPG_DO_DS_COUNT };
|
|||||||
|
|
||||||
static const struct do_table_entry
|
static const struct do_table_entry
|
||||||
gpg_do_table[] = {
|
gpg_do_table[] = {
|
||||||
/* Pseudo DO (private): not directly user accessible */
|
|
||||||
{ GNUK_DO_PRVKEY_SIG, DO_VAR, AC_NEVER, AC_NEVER, &do_ptr[0] },
|
|
||||||
{ GNUK_DO_PRVKEY_DEC, DO_VAR, AC_NEVER, AC_NEVER, &do_ptr[1] },
|
|
||||||
{ GNUK_DO_PRVKEY_AUT, DO_VAR, AC_NEVER, AC_NEVER, &do_ptr[2] },
|
|
||||||
{ GNUK_DO_KEYSTRING_PW1, DO_VAR, AC_NEVER, AC_NEVER, &do_ptr[3] },
|
|
||||||
{ GNUK_DO_KEYSTRING_RC, DO_VAR, AC_NEVER, AC_NEVER, &do_ptr[4] },
|
|
||||||
{ GNUK_DO_KEYSTRING_PW3, DO_VAR, AC_NEVER, AC_NEVER, &do_ptr[5] },
|
|
||||||
{ GNUK_DO_PW_STATUS, DO_VAR, AC_NEVER, AC_NEVER, &do_ptr[6] },
|
|
||||||
/* Variable(s): Fixed size, not changeable by user */
|
|
||||||
{ GPG_DO_DS_COUNT, DO_VAR, AC_ALWAYS, AC_NEVER, &do_ptr[7] },
|
|
||||||
/* Variables: Fixed size */
|
/* Variables: Fixed size */
|
||||||
{ GPG_DO_SEX, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[8] },
|
{ GPG_DO_SEX, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[0] },
|
||||||
{ GPG_DO_FP_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[9] },
|
{ GPG_DO_FP_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[1] },
|
||||||
{ GPG_DO_FP_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[10] },
|
{ GPG_DO_FP_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[2] },
|
||||||
{ GPG_DO_FP_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[11] },
|
{ GPG_DO_FP_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[3] },
|
||||||
{ GPG_DO_CAFP_1, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[12] },
|
{ GPG_DO_CAFP_1, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[4] },
|
||||||
{ GPG_DO_CAFP_2, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[13] },
|
{ GPG_DO_CAFP_2, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[5] },
|
||||||
{ GPG_DO_CAFP_3, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[14] },
|
{ GPG_DO_CAFP_3, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[6] },
|
||||||
{ GPG_DO_KGTIME_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[15] },
|
{ GPG_DO_KGTIME_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[7] },
|
||||||
{ GPG_DO_KGTIME_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[16] },
|
{ GPG_DO_KGTIME_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[8] },
|
||||||
{ GPG_DO_KGTIME_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[17] },
|
{ GPG_DO_KGTIME_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[9] },
|
||||||
/* Variables: Variable size */
|
/* Variables: Variable size */
|
||||||
{ GPG_DO_LOGIN_DATA, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[18] },
|
{ GPG_DO_LOGIN_DATA, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[10] },
|
||||||
{ GPG_DO_URL, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[19] },
|
{ GPG_DO_URL, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[11] },
|
||||||
{ GPG_DO_NAME, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[20] },
|
{ GPG_DO_NAME, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[12] },
|
||||||
{ GPG_DO_LANGUAGE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[21] },
|
{ GPG_DO_LANGUAGE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[13] },
|
||||||
{ GPG_DO_CH_CERTIFICATE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, &do_ptr[22] },
|
|
||||||
/* Pseudo DO READ: calculated */
|
/* Pseudo DO READ: calculated */
|
||||||
{ GPG_DO_HIST_BYTES, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_hist_bytes },
|
{ GPG_DO_HIST_BYTES, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_hist_bytes },
|
||||||
{ GPG_DO_FP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_fp_all },
|
{ GPG_DO_FP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_fp_all },
|
||||||
{ GPG_DO_CAFP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_cafp_all },
|
{ GPG_DO_CAFP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_cafp_all },
|
||||||
{ GPG_DO_KGTIME_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_kgtime_all },
|
{ GPG_DO_KGTIME_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_kgtime_all },
|
||||||
|
/* Pseudo DO READ: calculated, not changeable by user */
|
||||||
|
{ GPG_DO_DS_COUNT, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_ds_count },
|
||||||
/* Pseudo DO READ/WRITE: calculated */
|
/* Pseudo DO READ/WRITE: calculated */
|
||||||
{ GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
|
{ GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
|
||||||
rw_pw_status },
|
rw_pw_status },
|
||||||
@@ -854,60 +896,116 @@ gpg_do_table[] = {
|
|||||||
/* Simple data: write access only */
|
/* Simple data: write access only */
|
||||||
{ GPG_DO_RESETTING_CODE, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
|
{ GPG_DO_RESETTING_CODE, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
|
||||||
proc_resetting_code },
|
proc_resetting_code },
|
||||||
/* Compound data: Write access only*/
|
/* Compound data: Write access only */
|
||||||
{ GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
|
{ GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
|
||||||
proc_key_import },
|
proc_key_import },
|
||||||
|
/* Card holder certificate: Not supported yet */
|
||||||
|
{ GPG_DO_CH_CERTIFICATE, DO_PROC_READWRITE, AC_NEVER, AC_NEVER, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_DO_ENTRIES (int)(sizeof (gpg_do_table) / sizeof (struct do_table_entry))
|
#define NUM_DO_ENTRIES (int)(sizeof (gpg_do_table) / sizeof (struct do_table_entry))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize DO_PTR reading from Flash ROM
|
* Reading data from Flash ROM, initialize DO_PTR, PW_ERR_COUNTERS, etc.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
gpg_do_table_init (void)
|
gpg_do_table_init (void)
|
||||||
{
|
{
|
||||||
const uint8_t *p, *p_start;
|
const uint8_t *p, *p_start;
|
||||||
int i;
|
int i;
|
||||||
|
const uint8_t *dsc_h14_p, *dsc_l10_p;
|
||||||
|
int dsc_h14, dsc_l10;
|
||||||
|
|
||||||
do_ptr[NR_DO_DS_COUNT] = do_ds_count_initial_value;
|
p_start = flash_data_pool ();
|
||||||
do_ptr[NR_DO_PW_STATUS] = do_pw_status_bytes_template;
|
|
||||||
p_start = flash_do_pool ();
|
|
||||||
|
|
||||||
/* Traverse DO pool */
|
dsc_h14_p = dsc_l10_p = NULL;
|
||||||
|
pw1_lifetime_p = NULL;
|
||||||
|
pw_err_counter_p[PW_ERR_PW1] = NULL;
|
||||||
|
pw_err_counter_p[PW_ERR_RC] = NULL;
|
||||||
|
pw_err_counter_p[PW_ERR_PW3] = NULL;
|
||||||
|
|
||||||
|
/* Traverse DO and counters in DO pool */
|
||||||
p = p_start;
|
p = p_start;
|
||||||
while (*p != 0xff)
|
while (*p != NR_EMPTY)
|
||||||
{
|
{
|
||||||
uint8_t nr = *p++;
|
uint8_t nr = *p++;
|
||||||
uint8_t len = *p;
|
uint8_t second_byte = *p;
|
||||||
|
|
||||||
if (len == 0x00)
|
if (nr == 0x00 && second_byte == 0x00)
|
||||||
p++;
|
p++; /* Skip released word */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
do_ptr[nr] = p;
|
if (nr < 0x80)
|
||||||
p += len + 1;
|
{
|
||||||
|
/* It's Data Object */
|
||||||
|
do_ptr[nr - NR_DO__FIRST__] = p;
|
||||||
|
p += second_byte + 1;
|
||||||
|
|
||||||
if (((uint32_t)p & 1))
|
if (((uint32_t)p & 1))
|
||||||
p++;
|
p++;
|
||||||
|
}
|
||||||
|
else if (nr >= 0x80 && nr <= 0xbf)
|
||||||
|
/* Encoded data of Digital Signature Counter: upper 14-bit */
|
||||||
|
{
|
||||||
|
dsc_h14_p = p - 1;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else if (nr >= 0xc0 && nr <= 0xc3)
|
||||||
|
/* Encoded data of Digital Signature Counter: lower 10-bit */
|
||||||
|
{
|
||||||
|
dsc_l10_p = p - 1;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
switch (nr)
|
||||||
|
{
|
||||||
|
case NR_BOOL_PW1_LIFETIME:
|
||||||
|
pw1_lifetime_p = p - 1;
|
||||||
|
p++;
|
||||||
|
continue;
|
||||||
|
case NR_COUNTER_123:
|
||||||
|
if (second_byte <= PW_ERR_PW3)
|
||||||
|
pw_err_counter_p[second_byte] = ++p;
|
||||||
|
p += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flash_set_do_pool_last (p);
|
flash_set_data_pool_last (p);
|
||||||
|
|
||||||
num_prv_keys = 0;
|
num_prv_keys = 0;
|
||||||
if (do_ptr[NR_DO_PRVKEY_SIG] != NULL)
|
if (do_ptr[NR_DO_PRVKEY_SIG - NR_DO__FIRST__] != NULL)
|
||||||
num_prv_keys++;
|
num_prv_keys++;
|
||||||
if (do_ptr[NR_DO_PRVKEY_DEC] != NULL)
|
if (do_ptr[NR_DO_PRVKEY_DEC - NR_DO__FIRST__] != NULL)
|
||||||
num_prv_keys++;
|
num_prv_keys++;
|
||||||
if (do_ptr[NR_DO_PRVKEY_AUT] != NULL)
|
if (do_ptr[NR_DO_PRVKEY_AUT - NR_DO__FIRST__] != NULL)
|
||||||
num_prv_keys++;
|
num_prv_keys++;
|
||||||
|
|
||||||
data_objects_number_of_bytes = 0;
|
data_objects_number_of_bytes = 0;
|
||||||
for (i = 0; i < NR_DO_LAST; i++)
|
for (i = NR_DO__FIRST__; i < NR_DO__LAST__; i++)
|
||||||
if (do_ptr[i] != NULL)
|
if (do_ptr[i - NR_DO__FIRST__] != NULL)
|
||||||
data_objects_number_of_bytes += *do_ptr[i];
|
data_objects_number_of_bytes += *do_ptr[i - NR_DO__FIRST__];
|
||||||
|
|
||||||
|
|
||||||
|
if (dsc_l10_p == NULL)
|
||||||
|
dsc_l10 = 0;
|
||||||
|
else
|
||||||
|
dsc_l10 = ((*dsc_l10_p - 0xc0) << 8) | *(dsc_l10_p + 1);
|
||||||
|
|
||||||
|
if (dsc_h14_p == NULL)
|
||||||
|
dsc_h14 = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dsc_h14 = ((*dsc_h14_p - 0x80) << 8) | *(dsc_h14_p + 1);
|
||||||
|
if (dsc_l10_p == NULL)
|
||||||
|
DEBUG_INFO ("something wrong in DSC\r\n"); /* weird??? */
|
||||||
|
else if (dsc_l10_p < dsc_h14_p)
|
||||||
|
/* Possibly, power off during writing dsc_l10 */
|
||||||
|
dsc_l10 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
digital_signature_counter = (dsc_h14 << 10) | dsc_l10;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1086,7 +1184,7 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len)
|
|||||||
/* make DO empty */
|
/* make DO empty */
|
||||||
*do_data_p = NULL;
|
*do_data_p = NULL;
|
||||||
else if (len > 255)
|
else if (len > 255)
|
||||||
GPG_MEMORY_FAILURE();
|
GPG_MEMORY_FAILURE ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint8_t nr = do_tag_to_nr (tag);
|
uint8_t nr = do_tag_to_nr (tag);
|
||||||
@@ -1095,7 +1193,7 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len)
|
|||||||
if (*do_data_p)
|
if (*do_data_p)
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
else
|
else
|
||||||
GPG_MEMORY_FAILURE();
|
GPG_MEMORY_FAILURE ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1131,11 +1229,11 @@ gpg_do_public_key (uint8_t kk_byte)
|
|||||||
DEBUG_BYTE (kk_byte);
|
DEBUG_BYTE (kk_byte);
|
||||||
|
|
||||||
if (kk_byte == 0xb6)
|
if (kk_byte == 0xb6)
|
||||||
do_data = do_ptr[NR_DO_PRVKEY_SIG];
|
do_data = do_ptr[NR_DO_PRVKEY_SIG - NR_DO__FIRST__];
|
||||||
else if (kk_byte == 0xb8)
|
else if (kk_byte == 0xb8)
|
||||||
do_data = do_ptr[NR_DO_PRVKEY_DEC];
|
do_data = do_ptr[NR_DO_PRVKEY_DEC - NR_DO__FIRST__];
|
||||||
else /* 0xa4 */
|
else /* 0xa4 */
|
||||||
do_data = do_ptr[NR_DO_PRVKEY_AUT];
|
do_data = do_ptr[NR_DO_PRVKEY_AUT - NR_DO__FIRST__];
|
||||||
|
|
||||||
if (do_data == NULL)
|
if (do_data == NULL)
|
||||||
{
|
{
|
||||||
@@ -1180,7 +1278,7 @@ gpg_do_read_simple (uint8_t nr)
|
|||||||
{
|
{
|
||||||
const uint8_t *do_data;
|
const uint8_t *do_data;
|
||||||
|
|
||||||
do_data = do_ptr[nr];
|
do_data = do_ptr[nr - NR_DO__FIRST__];
|
||||||
if (do_data == NULL)
|
if (do_data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -1192,7 +1290,7 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
|
|||||||
{
|
{
|
||||||
const uint8_t **do_data_p;
|
const uint8_t **do_data_p;
|
||||||
|
|
||||||
do_data_p = (const uint8_t **)&do_ptr[nr];
|
do_data_p = (const uint8_t **)&do_ptr[nr - NR_DO__FIRST__];
|
||||||
if (*do_data_p)
|
if (*do_data_p)
|
||||||
flash_do_release (*do_data_p);
|
flash_do_release (*do_data_p);
|
||||||
|
|
||||||
@@ -1202,7 +1300,7 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
|
|||||||
if (*do_data_p)
|
if (*do_data_p)
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
else
|
else
|
||||||
GPG_MEMORY_FAILURE();
|
GPG_MEMORY_FAILURE ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1210,55 +1308,3 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
|
|||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
gpg_do_increment_digital_signature_counter (void)
|
|
||||||
{
|
|
||||||
const uint8_t *do_data;
|
|
||||||
uint32_t count;
|
|
||||||
uint8_t count_data[SIZE_DIGITAL_SIGNATURE_COUNTER];
|
|
||||||
|
|
||||||
do_data = do_ptr[NR_DO_DS_COUNT];
|
|
||||||
if (do_data == NULL) /* No object means count 0 */
|
|
||||||
count = 0;
|
|
||||||
else
|
|
||||||
count = (do_data[1]<<16) | (do_data[2]<<8) | do_data[3];
|
|
||||||
|
|
||||||
count++;
|
|
||||||
count_data[0] = (count >> 16) & 0xff;
|
|
||||||
count_data[1] = (count >> 8) & 0xff;
|
|
||||||
count_data[2] = count & 0xff;
|
|
||||||
|
|
||||||
if (do_data)
|
|
||||||
flash_do_release (do_data);
|
|
||||||
do_ptr[NR_DO_DS_COUNT] = flash_do_write (NR_DO_DS_COUNT, count_data,
|
|
||||||
SIZE_DIGITAL_SIGNATURE_COUNTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gpg_do_reset_pw_counter (uint8_t which)
|
|
||||||
{
|
|
||||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
|
||||||
const uint8_t *do_data = do_ptr[NR_DO_PW_STATUS];
|
|
||||||
|
|
||||||
/* Reset PW1/RC/PW3 counter in GNUK_DO_PW_STATUS */
|
|
||||||
if (do_data)
|
|
||||||
{
|
|
||||||
memcpy (pwsb, &do_data[1], SIZE_PW_STATUS_BYTES);
|
|
||||||
if (pwsb[which] == 3)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pwsb[which] = 3;
|
|
||||||
flash_do_release (do_data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy (pwsb, PW_STATUS_BYTES_TEMPLATE, SIZE_PW_STATUS_BYTES);
|
|
||||||
if (pwsb[which] == 3)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pwsb[which] = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -246,20 +246,20 @@ cmd_change_password (void)
|
|||||||
{
|
{
|
||||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||||
ac_reset_pso_cds ();
|
ac_reset_pso_cds ();
|
||||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||||
DEBUG_INFO ("Changed DO_KEYSTRING_PW1.\r\n");
|
DEBUG_INFO ("Changed DO_KEYSTRING_PW1.\r\n");
|
||||||
}
|
}
|
||||||
else if (r > 0 && who == BY_USER)
|
else if (r > 0 && who == BY_USER)
|
||||||
{
|
{
|
||||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
|
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
|
||||||
ac_reset_pso_cds ();
|
ac_reset_pso_cds ();
|
||||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||||
DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
|
DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
|
||||||
}
|
}
|
||||||
else /* r >= 0 && who == BY_ADMIN */
|
else /* r >= 0 && who == BY_ADMIN */
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("done.\r\n");
|
DEBUG_INFO ("done.\r\n");
|
||||||
gpg_do_reset_pw_counter (PW_STATUS_PW3);
|
gpg_reset_pw_err_counter (PW_ERR_PW3);
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,12 +287,10 @@ cmd_reset_user_password (void)
|
|||||||
|
|
||||||
if (p1 == 0x00) /* by User with Reseting Code */
|
if (p1 == 0x00) /* by User with Reseting Code */
|
||||||
{
|
{
|
||||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
|
||||||
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
||||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||||
|
|
||||||
if (pw_status_bytes == NULL
|
if (gpg_passwd_locked (PW_ERR_RC))
|
||||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("blocked.\r\n");
|
DEBUG_INFO ("blocked.\r\n");
|
||||||
GPG_SECURITY_AUTH_BLOCKED ();
|
GPG_SECURITY_AUTH_BLOCKED ();
|
||||||
@@ -320,29 +318,27 @@ cmd_reset_user_password (void)
|
|||||||
}
|
}
|
||||||
else if (r < 0)
|
else if (r < 0)
|
||||||
{
|
{
|
||||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
|
||||||
|
|
||||||
sec_fail:
|
sec_fail:
|
||||||
DEBUG_INFO ("failed.\r\n");
|
DEBUG_INFO ("failed.\r\n");
|
||||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
gpg_increment_pw_err_counter (PW_ERR_RC);
|
||||||
pwsb[PW_STATUS_RC]--;
|
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
GPG_SECURITY_FAILURE ();
|
GPG_SECURITY_FAILURE ();
|
||||||
}
|
}
|
||||||
else if (r == 0)
|
else if (r == 0)
|
||||||
{
|
{
|
||||||
if (memcmp (ks_rc+1, old_ks, KEYSTRING_MD_SIZE) != 0)
|
if (memcmp (ks_rc+1, old_ks, KEYSTRING_MD_SIZE) != 0)
|
||||||
goto sec_fail;
|
goto sec_fail;
|
||||||
|
DEBUG_INFO ("done (no prvkey).\r\n");
|
||||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||||
ac_reset_pso_cds ();
|
ac_reset_pso_cds ();
|
||||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
gpg_reset_pw_err_counter (PW_ERR_RC);
|
||||||
DEBUG_INFO ("done (no prvkey).\r\n");
|
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("done.\r\n");
|
DEBUG_INFO ("done.\r\n");
|
||||||
ac_reset_pso_cds ();
|
ac_reset_pso_cds ();
|
||||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
gpg_reset_pw_err_counter (PW_ERR_RC);
|
||||||
|
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -377,13 +373,13 @@ cmd_reset_user_password (void)
|
|||||||
DEBUG_INFO ("done (no privkey).\r\n");
|
DEBUG_INFO ("done (no privkey).\r\n");
|
||||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||||
ac_reset_pso_cds ();
|
ac_reset_pso_cds ();
|
||||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("done.\r\n");
|
DEBUG_INFO ("done.\r\n");
|
||||||
ac_reset_pso_cds ();
|
ac_reset_pso_cds ();
|
||||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -567,24 +563,18 @@ cmd_pso (void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* Success */
|
{ /* Success */
|
||||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
if (gpg_get_pw1_lifetime ())
|
||||||
|
|
||||||
if (pw_status_bytes[0] == 0)
|
|
||||||
ac_reset_pso_cds ();
|
ac_reset_pso_cds ();
|
||||||
|
|
||||||
gpg_do_increment_digital_signature_counter ();
|
gpg_increment_digital_signature_counter ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
|
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
|
||||||
{
|
{
|
||||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
|
||||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
|
||||||
|
|
||||||
DEBUG_SHORT (len);
|
DEBUG_SHORT (len);
|
||||||
|
|
||||||
if (pw_status_bytes == NULL
|
if (gpg_passwd_locked (PW_ERR_PW1)
|
||||||
|| pw_status_bytes[PW_STATUS_PW1] == 0 /* locked */
|
|
||||||
|| !ac_check_status (AC_PSO_OTHER_AUTHORIZED))
|
|| !ac_check_status (AC_PSO_OTHER_AUTHORIZED))
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("security error.");
|
DEBUG_INFO ("security error.");
|
||||||
@@ -592,20 +582,16 @@ cmd_pso (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
|
||||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER,
|
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER,
|
||||||
pw1_keystring + 1)) < 0)
|
pw1_keystring + 1)) < 0)
|
||||||
{
|
{
|
||||||
pwsb[PW_STATUS_PW1]--;
|
gpg_increment_pw_err_counter (PW_ERR_PW1);
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
GPG_SECURITY_FAILURE ();
|
GPG_SECURITY_FAILURE ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (pwsb[PW_STATUS_PW1] != 3) /* Failure in the past? */
|
else
|
||||||
{ /* Reset counter as it's success now */
|
/* Reset counter as it's success now */
|
||||||
pwsb[PW_STATUS_PW1] = 3;
|
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ac_reset_pso_other ();
|
ac_reset_pso_other ();
|
||||||
|
|
||||||
@@ -634,8 +620,6 @@ cmd_internal_authenticate (void)
|
|||||||
int len = cmd_APDU[4];
|
int len = cmd_APDU[4];
|
||||||
int data_start = 5;
|
int data_start = 5;
|
||||||
int r;
|
int r;
|
||||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
|
|
||||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
{
|
{
|
||||||
@@ -649,8 +633,7 @@ cmd_internal_authenticate (void)
|
|||||||
{
|
{
|
||||||
DEBUG_SHORT (len);
|
DEBUG_SHORT (len);
|
||||||
|
|
||||||
if (pw_status_bytes == NULL
|
if (gpg_passwd_locked (PW_ERR_PW1)
|
||||||
|| pw_status_bytes[PW_STATUS_PW1] == 0 /* locked */
|
|
||||||
|| !ac_check_status (AC_PSO_OTHER_AUTHORIZED))
|
|| !ac_check_status (AC_PSO_OTHER_AUTHORIZED))
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("security error.");
|
DEBUG_INFO ("security error.");
|
||||||
@@ -658,20 +641,16 @@ cmd_internal_authenticate (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
|
||||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER,
|
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER,
|
||||||
pw1_keystring + 1)) < 0)
|
pw1_keystring + 1)) < 0)
|
||||||
{
|
{
|
||||||
pwsb[PW_STATUS_PW1]--;
|
gpg_increment_pw_err_counter (PW_ERR_PW1);
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
GPG_SECURITY_FAILURE ();
|
GPG_SECURITY_FAILURE ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (pwsb[PW_STATUS_PW1] != 3) /* Failure in the past? */
|
else
|
||||||
{ /* Reset counter as it's success now */
|
/* Reset counter as it's success now */
|
||||||
pwsb[PW_STATUS_PW1] = 3;
|
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||||
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
ac_reset_pso_other ();
|
ac_reset_pso_other ();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user