From ffa9bf1f944587313a36a0bf88a2a5d55e110f5a Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 14 Oct 2016 08:45:01 +0900 Subject: [PATCH] support factory_reset. --- ChangeLog | 21 ++++++++++++++++ NEWS | 16 ++++++++++++ src/gnuk.h | 1 + src/openpgp-do.c | 30 +++++++---------------- src/openpgp.c | 17 +++---------- src/usb-ccid.c | 4 +++ test/features/002_get_data_static.feature | 2 +- test/features/402_get_data_static.feature | 2 +- test/features/802_get_data_static.feature | 2 +- tests/test_empty_card.py | 3 ++- 10 files changed, 60 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index fa11517..82c4736 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2016-10-14 Niibe Yutaka + + * src/usb-ccid.c (ccid_power_on) [LIFE_CYCLE_MANAGEMENT_SUPPORT]: + Change LCS value in ATR at run time. + + * src/openpgp.c (gpg_init): Handle FILE_CARD_TERMINATED. + (cmd_select_file): Don't return AID. + (cmd_activate_file, cmd_terminate_df): New. + (process_command_apdu): Let return GPG_NO_RECORD() when + not selected. + + * src/openpgp-do.c (gpg_do_terminate): New. + (gpg_data_scan): Handle p_start is NULL. + (do_hist_bytes): Remove. + + * src/flash.c (flash_data): Change the value from 0x0000. + (flash_init): Support termination state. Fix handling + of the boundary case where gen0 is 0xfffe. + (flash_terminate, flash_activate): New. + (flash_copying_gc): Skip 0xffff for generation number. + 2016-10-13 Niibe Yutaka * src/status-code.h: Rename from openpgp.h. diff --git a/NEWS b/NEWS index e0de640..4d3c3ee 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,21 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 1.2.2 + + Released 2016-10-14, by NIIBE Yutaka + +** Change of SELECT FILE behavior +Gnuk used to reply AID upon SELECT FILE command. Now, to be compatible +to original OpenPGP card, it returns nothing but status code of 9000. + +** Added feature of Factory Reset as compile time option +Original OpenPGP card has the feature, and Gnuk is now configurable to +support the feature. + +** Upgrade of Chopstx +We use Chopstx 1.2. + + * Major changes in Gnuk 1.2.1 Released 2016-07-11, by NIIBE Yutaka diff --git a/src/gnuk.h b/src/gnuk.h index 5586040..d6c6f67 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -100,6 +100,7 @@ void ac_fini (void); void set_res_sw (uint8_t sw1, uint8_t sw2); +extern uint8_t file_selection; extern const uint8_t historical_bytes[]; extern uint16_t data_objects_number_of_bytes; diff --git a/src/openpgp-do.c b/src/openpgp-do.c index be21f29..5f5f7de 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -90,10 +90,10 @@ uint16_t data_objects_number_of_bytes; /* * Compile time vars: - * Historical Bytes (template), Extended Capabilities. + * Historical Bytes, Extended Capabilities. */ -/* Historical Bytes (template) */ +/* Historical Bytes */ const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = { 10, 0x00, @@ -102,7 +102,12 @@ const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = { 0x80, 0x01, 0x80, /* Full DF name */ /* 1-byte */ /* Command chaining, No extended Lc and Le */ - 0x00, 0x90, 0x00 /* Status info (no life cycle management) */ +#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT + 0x05, +#else + 0x00, +#endif + 0x90, 0x00 /* Status info */ }; /* Extended Capabilities */ @@ -485,23 +490,6 @@ copy_tag (uint16_t tag) } } -static int -do_hist_bytes (uint16_t tag, int with_tag) -{ - /* - * Currently, we support no life cycle management. In case of Gnuk, - * user could flash the MCU with SWD/JTAG, instead. It is also - * possible for user to do firmware upgrade through USB. - * - * Thus, here, it just returns the template as is. - * - * In future (when Gnuk will be on the real smartcard), - * we can support life cycle management by implementing - * TERMINATE DF / ACTIVATE FILE and fix code around here. - */ - copy_do_1 (tag, historical_bytes, with_tag); - return 1; -} #define SIZE_FP 20 #define SIZE_KGTIME 4 @@ -1513,7 +1501,6 @@ gpg_do_table[] = { { 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[13] }, /* Pseudo DO READ: calculated */ - { 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_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 }, @@ -1530,6 +1517,7 @@ gpg_do_table[] = { { GPG_DO_ALG_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_algorithm_attr }, /* Fixed data */ + { GPG_DO_HIST_BYTES, DO_FIXED, AC_ALWAYS, AC_NEVER, historical_bytes }, { GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities }, /* Compound data: Read access only */ { GPG_DO_CH_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ch_data }, diff --git a/src/openpgp.c b/src/openpgp.c index b4b9f40..a30450a 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -101,7 +101,7 @@ set_res_sw (uint8_t sw1, uint8_t sw2) #define FILE_CARD_TERMINATED_OPENPGP 254 #define FILE_CARD_TERMINATED 255 -static uint8_t file_selection; +uint8_t file_selection; static void gpg_init (void) @@ -765,18 +765,9 @@ cmd_select_file (void) } file_selection = FILE_DF_OPENPGP; - if ((P2 (apdu) & 0x0c) == 0x0c) /* No FCI */ - GPG_SUCCESS (); - else - { - gpg_do_get_data (0x004f, 1); /* AID */ - memmove (res_APDU+2, res_APDU, res_APDU_size); - res_APDU[0] = 0x6f; - res_APDU[1] = 0x12; - res_APDU[2] = 0x84; /* overwrite: DF name */ - res_APDU_size += 2; - GPG_SUCCESS (); - } + + /* Behave just like original OpenPGP card. */ + GPG_SUCCESS (); } else if (apdu.cmd_apdu_data_len == 2 && apdu.cmd_apdu_data[0] == 0x2f && apdu.cmd_apdu_data[1] == 0x02) diff --git a/src/usb-ccid.c b/src/usb-ccid.c index 736d4ee..c533e13 100644 --- a/src/usb-ccid.c +++ b/src/usb-ccid.c @@ -795,6 +795,10 @@ ccid_power_on (struct ccid *c) memcpy (p + CCID_MSG_HEADER_SIZE, ATR_head, sizeof (ATR_head)); memcpy (p + CCID_MSG_HEADER_SIZE + sizeof (ATR_head), historical_bytes + 1, historical_bytes[0]); +#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT + if (file_selection == 255) + p[CCID_MSG_HEADER_SIZE + sizeof (ATR_head) + 7] = 0x03; +#endif for (i = 1; i < (int)size_atr - 1; i++) xor_check ^= p[CCID_MSG_HEADER_SIZE + i]; p[CCID_MSG_HEADER_SIZE+size_atr-1] = xor_check; diff --git a/test/features/002_get_data_static.feature b/test/features/002_get_data_static.feature index 4815aeb..290e98e 100644 --- a/test/features/002_get_data_static.feature +++ b/test/features/002_get_data_static.feature @@ -4,7 +4,7 @@ Feature: command GET DATA Scenario: data object historical bytes When requesting historical bytes: 5f52 - Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00 + Then data should match: \x00\x31\x84\x73\x80\x01\x80[\x00\x05]\x90\x00 Scenario: data object extended capabilities When requesting extended capabilities: c0 diff --git a/test/features/402_get_data_static.feature b/test/features/402_get_data_static.feature index 4815aeb..290e98e 100644 --- a/test/features/402_get_data_static.feature +++ b/test/features/402_get_data_static.feature @@ -4,7 +4,7 @@ Feature: command GET DATA Scenario: data object historical bytes When requesting historical bytes: 5f52 - Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00 + Then data should match: \x00\x31\x84\x73\x80\x01\x80[\x00\x05]\x90\x00 Scenario: data object extended capabilities When requesting extended capabilities: c0 diff --git a/test/features/802_get_data_static.feature b/test/features/802_get_data_static.feature index 4815aeb..290e98e 100644 --- a/test/features/802_get_data_static.feature +++ b/test/features/802_get_data_static.feature @@ -4,7 +4,7 @@ Feature: command GET DATA Scenario: data object historical bytes When requesting historical bytes: 5f52 - Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00 + Then data should match: \x00\x31\x84\x73\x80\x01\x80[\x00\x05]\x90\x00 Scenario: data object extended capabilities When requesting extended capabilities: c0 diff --git a/tests/test_empty_card.py b/tests/test_empty_card.py index f70e7c0..8199f1a 100644 --- a/tests/test_empty_card.py +++ b/tests/test_empty_card.py @@ -133,7 +133,8 @@ def test_verify_pw3(card): def test_historical_bytes(card): h = get_data_object(card, 0x5f52) assert h == b'\x001\xc5s\xc0\x01@\x05\x90\x00' or \ - h == b'\x00\x31\x84\x73\x80\x01\x80\x00\x90\x00' + h == b'\x00\x31\x84\x73\x80\x01\x80\x00\x90\x00' or \ + h == b'\x00\x31\x84\x73\x80\x01\x80\x05\x90\x00' def test_extended_capabilities(card): a = get_data_object(card, 0xc0)