diff --git a/ChangeLog b/ChangeLog index 1b1e82f..54652f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2011-02-08 NIIBE Yutaka + + * tool/gnuk_put_binary.py: Renamed (was: gnuk_update_binary.py). + (gnuk_token.cmd_write_binary): New. + (main): Support writing serial number. + + * GNUK_SERIAL_NUMBER: Renamed (was: FSIJ_SERIAL_NUMBER). + + * src/config.h.in (@SERIAL_DEFINE@): Removed. + + * src/gnuk.h (FILEID_SERIAL_NO): New. + + * src/openpgp.c (INS_WRITE_BINARY, cmd_write_binary): New. + + * src/configure: Remove --with-fixed-serial support. + + * src/openpgp-do.c (do_openpgpcard_aid): Remove support of + SERIAL_NUMBER_IN_AID. + + * src/flash.c (flash_write_binary): Support FILEID_SERIAL_NO. + 2011-02-04 NIIBE Yutaka * tool/gnuk_update_binary.py: Support updating random bits. diff --git a/FSIJ_SERIAL_NUMBER b/FSIJ_SERIAL_NUMBER deleted file mode 100644 index ecad1f5..0000000 --- a/FSIJ_SERIAL_NUMBER +++ /dev/null @@ -1,2 +0,0 @@ -# Email # 4-byte serial number, separated by ':' -gniibe@fsij.org 00:00:00:01 diff --git a/GNUK_SERIAL_NUMBER b/GNUK_SERIAL_NUMBER new file mode 100644 index 0000000..8e06dae --- /dev/null +++ b/GNUK_SERIAL_NUMBER @@ -0,0 +1,2 @@ +# Email # 6-byte serial number, separated by ':' +gniibe@fsij.org f5:17:00:00:00:01 diff --git a/src/config.h.in b/src/config.h.in index f599b0d..4d77b5f 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -2,7 +2,6 @@ #ifdef DEBUG #define ENABLE_VIRTUAL_COM_PORT 1 #endif -@SERIAL_DEFINE@ @DFU_DEFINE@ @PINPAD_DEFINE@ @PINPAD_MORE_DEFINE@ diff --git a/src/configure b/src/configure index b79fc59..5a15035 100755 --- a/src/configure +++ b/src/configure @@ -24,7 +24,6 @@ help=no target=OLIMEX_STM32_H103 verbose=no with_dfu=default -with_fixed_serial=no debug=no pinpad=no @@ -62,10 +61,6 @@ for option; do with_dfu=yes ;; --without-dfu) with_dfu=no ;; - --with-fixed-serial) - with_fixed_serial=yes ;; - --without-fixed-serial) - with_fixed_serial=no ;; *) echo "Unrecognized option \`$option'" >&2 echo "Try \`$0 --help' for more information." >&2 @@ -94,7 +89,6 @@ Configuration: --enable-pinpad={cir,dial} PIN input device support [no] --with-dfu build image for DFU [] - --with-fixed-serial Use fixed serial number [no: chip unique ID] EOF exit 0 fi @@ -135,20 +129,6 @@ STM8S_DISCOVERY) ;; esac -# --with-fixed-serial option -if test "$with_fixed_serial" = "no"; then - echo "Using chip unique ID for card AID" - SERIAL_DEFINE="#undef SERIAL_NUMBER_IN_AID" -else - echo "Using fixed serial number (at compile time) for card AID" - if test "x$MAIL" = "x"; then - echo "ERROR: Please set MAIL shell variable to select FSIJ serial number" >&2 - exit 1 - fi - SERIAL=`sed -n -e "/^$MAIL/s/^.* \(..\):\(..\):\(..\):\(..\)/0x\1, 0x\2, 0x\3, 0x\4/p" ../FSIJ_SERIAL_NUMBER` - SERIAL_DEFINE="#define SERIAL_NUMBER_IN_AID $SERIAL" -fi - # --enable-debug option if test "$debug" = "yes"; then DEBUG_MAKE_OPTION="ENABLE_DEBUG=1" @@ -201,6 +181,5 @@ sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \ -e "s/@PINPAD_DEFINE@/$PINPAD_DEFINE/" \ -e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_DEFINE/" \ -e "s/@DFU_DEFINE@/$DFU_DEFINE/" \ - -e "s/@SERIAL_DEFINE@/$SERIAL_DEFINE/" \ < config.h.in > config.h exit 0 diff --git a/src/flash.c b/src/flash.c index a3bea09..986db89 100644 --- a/src/flash.c +++ b/src/flash.c @@ -646,6 +646,11 @@ flash_write_binary (uint8_t file_id, const uint8_t *data, maxsize = FLASH_PAGE_SIZE; p = &random_bits_start; } + else if (file_id == FILEID_SERIAL_NO) + { + maxsize = 6; + p = &openpgpcard_aid[8]; + } else return -1; diff --git a/src/gnuk.h b/src/gnuk.h index b3163c8..94adf10 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -118,6 +118,7 @@ extern void flash_reset_counter (uint8_t counter_tag_nr); #define FILEID_CH_CERTIFICATE 0 #define FILEID_RANDOM 1 +#define FILEID_SERIAL_NO 2 extern int flash_erase_binary (uint8_t file_id); extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset); @@ -305,7 +306,7 @@ extern uint8_t pw1_keystring[KEYSTRING_SIZE_PW1]; #define OPENPGP_CARD_INITIAL_PW3 "12345678" #endif -extern const uint8_t openpgpcard_aid[17] __attribute__ ((aligned (1))); +extern const uint8_t openpgpcard_aid[14]; extern int gpg_get_pw1_lifetime (void); diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 7df6bc9..d7571ba 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -406,23 +406,17 @@ do_kgtime_all (uint16_t tag, int with_tag) return 1; } -const uint8_t openpgpcard_aid_template[] = { +const uint8_t openpgpcard_aid[] = { 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01, 0x02, 0x00, /* Version 2.0 */ -#if defined(SERIAL_NUMBER_IN_AID) - 0xf5, 0x17, /* Manufacturer: FSIJ */ - SERIAL_NUMBER_IN_AID -#else - 0xff, 0xfe, /* Random bytes */ -#endif + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */ + /* v. id */ /* serial number */ }; static int do_openpgpcard_aid (uint16_t tag, int with_tag) { -#if !defined(SERIAL_NUMBER_IN_AID) - const uint8_t *u = unique_device_id (); -#endif + const uint16_t *vid_p = (const uint16_t *)&openpgpcard_aid[8]; if (with_tag) { @@ -430,14 +424,28 @@ do_openpgpcard_aid (uint16_t tag, int with_tag) *res_p++ = 16; } - memcpy (res_p, openpgpcard_aid_template, sizeof (openpgpcard_aid_template)); - res_p += sizeof (openpgpcard_aid_template); -#if !defined(SERIAL_NUMBER_IN_AID) - memcpy (res_p, u, 4); - res_p += 4; -#endif + if (*vid_p == 0xffff || *vid_p == 0x0000) + { + const uint8_t *u = unique_device_id (); + + memcpy (res_p, openpgpcard_aid, 8); + res_p += 8; + + /* vid == 0xfffe: serial number is random byte */ + *res_p++ = 0xff; + *res_p++ = 0xfe; + memcpy (res_p, u, 4); + res_p += 4; + } + else + { + memcpy (res_p, openpgpcard_aid, 14); + res_p += 14; + } + *res_p++ = 0; *res_p++ = 0; + return 1; } diff --git a/src/openpgp.c b/src/openpgp.c index 172058c..8b10e3f 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -38,6 +38,7 @@ #define INS_SELECT_FILE 0xa4 #define INS_READ_BINARY 0xb0 #define INS_GET_DATA 0xca +#define INS_WRITE_BINARY 0xd0 #define INS_UPDATE_BINARY 0xd6 #define INS_PUT_DATA 0xda #define INS_PUT_DATA_ODD 0xdb /* For key import */ @@ -916,6 +917,68 @@ cmd_update_binary (void) } +static void +cmd_write_binary (void) +{ + int len = cmd_APDU[4]; + int data_start = 5; + uint16_t offset; + int r; + + if (len == 0) + { + len = (cmd_APDU[5]<<8) | cmd_APDU[6]; + data_start = 7; + } + + DEBUG_INFO (" - WRITE BINARY\r\n"); + + if (gpg_passwd_locked (PW_ERR_PW3) || !ac_check_status (AC_ADMIN_AUTHORIZED)) + { + DEBUG_INFO ("security error."); + GPG_SECURITY_FAILURE (); + return; + } + + if ((cmd_APDU[2] & 0x80)) + if ((cmd_APDU[2] & 0x7f) == FILEID_SERIAL_NO) + { + file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f); + offset = 0; + } + else + { + GPG_NO_FILE (); + return; + } + else + { + if (file_selection != FILEID_SERIAL_NO) + { + GPG_COMMAND_NOT_ALLOWED (); + return; + } + + offset = (cmd_APDU[2] << 8) | cmd_APDU[3]; + } + + DEBUG_SHORT (len); + DEBUG_SHORT (offset); + + r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE, + &cmd_APDU[data_start], len, offset); + if (r < 0) + { + DEBUG_INFO ("memory error.\r\n"); + GPG_MEMORY_FAILURE (); + return; + } + + GPG_SUCCESS (); + DEBUG_INFO ("WRITE BINARY done.\r\n"); +} + + struct command { uint8_t command; @@ -932,6 +995,7 @@ const struct command cmds[] = { { INS_SELECT_FILE, cmd_select_file }, { INS_READ_BINARY, cmd_read_binary }, { INS_GET_DATA, cmd_get_data }, + { INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */ { INS_UPDATE_BINARY, cmd_update_binary }, /* Not in OpenPGP card protocol */ { INS_PUT_DATA, cmd_put_data }, { INS_PUT_DATA_ODD, cmd_put_data }, diff --git a/tool/gnuk_update_binary.py b/tool/gnuk_put_binary.py similarity index 79% rename from tool/gnuk_update_binary.py rename to tool/gnuk_put_binary.py index f72e7c4..f824b44 100755 --- a/tool/gnuk_update_binary.py +++ b/tool/gnuk_put_binary.py @@ -1,7 +1,7 @@ #! /usr/bin/python """ -gnuk_update_binary.py - a tool to put binary to Gnuk Token +gnuk_put_binary.py - a tool to put binary to Gnuk Token This tool is for importing certificate, updating random number, etc. Copyright (C) 2011 Free Software Initiative of Japan @@ -25,7 +25,7 @@ along with this program. If not, see . from intel_hex import * from struct import * -import sys, time, os +import sys, time, os, binascii # INPUT: binary file @@ -166,6 +166,21 @@ class gnuk_token: if not (sw[0] == 0x90 and sw[1] == 0x00): raise ValueError, "cmd_verify" + def cmd_write_binary(self, fileid, data): + count = 0 + data_len = len(data) + while count*256 < data_len: + if count == 0: + cmd_data = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:256]) + else: + cmd_data = iso7816_compose(0xd0, count, 0x00, data[256*count:256*(count+1)]) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, "cmd_write_binary" + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, "cmd_write_binary" + count += 1 + def cmd_update_binary(self, fileid, data): count = 0 data_len = len(data) @@ -218,12 +233,7 @@ def get_device(): return dev, config, alt raise ValueError, "Device not found" -def main(fileid, filename): - f = open(filename) - data = f.read() - f.close() - print "%s: %d" % (filename, len(data)) - data += "\x90\x00" +def main(fileid, is_update, data): dev, config, intf = get_device() print "Device: ", dev.filename print "Configuration: ", config.value @@ -234,7 +244,10 @@ def main(fileid, filename): elif icc.icc_get_status() == 1: icc.icc_power_on() icc.cmd_verify(3, "12345678") - icc.cmd_update_binary(fileid, data) + if is_update: + icc.cmd_update_binary(fileid, data) + else: + icc.cmd_write_binary(fileid, data) icc.cmd_select_openpgp() data = data[:-2] data_in_device = icc.cmd_get_data(0x7f, 0x21) @@ -243,10 +256,46 @@ def main(fileid, filename): return 0 if __name__ == '__main__': - if os.path.basename(sys.argv[1] == "random_bits"): - fileid = 1 + if sys.argv[1] == '-u': + is_update = True + sys.argv.pop(1) + else: + is_update = False + if sys.argv[1] == '-s': + fileid = 2 # serial number + filename = sys.argv[2] + f = open(filename) + email = os.environ['MAIL'] + serial_data_hex = None + for line in f.readlines(): + field = string.split(line) + if field[0] == os.environ['MAIL']: + serial_data_hex = field[1].replace(':','') + f.close() + if not serial_data_hex: + print "No serial number" + exit 1 + print "Writing serial number" + data = binascii.unhexlify(serial_data_hex) + elif sys.argv[1] == '-r': + fileid = 1 # Random number bits + if len(sys.argv) == 3: + filename = sys.argv[2] + f = open(filename) + else: + filename = stdin + f = sys.stdin + data = f.read() + f.close() + print "%s: %d" % (filename, len(data)) print "Updating random bits" else: fileid = 0 # Card holder certificate + filename = sys.argv[2] + f = open(filename) + data = f.read() + f.close() + print "%s: %d" % (filename, len(data)) + data += "\x90\x00" print "Updating card holder certificate" - main(fileid, sys.argv[1]) + main(fileid, is_update, data)