diff --git a/ChangeLog b/ChangeLog index b18c49b..93a69d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-01-19 Niibe Yutaka + + * src/usb-icc.c (icc_handle_data): Handle the case when it only + sends 0x90 and 0x00 correctly. + + * src/openpgp-do.c (gpg_do_get_data): Fix res_apdu_data_len. + 2012-01-18 Niibe Yutaka Clean up API between application layer and CCID layer. diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 47cec3b..b91b10b 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1253,7 +1253,10 @@ gpg_do_get_data (uint16_t tag, int with_tag) apdu.res_apdu_data = &ch_certificate_start; apdu.res_apdu_data_len = ((apdu.res_apdu_data[2] << 8) | apdu.res_apdu_data[3]); if (apdu.res_apdu_data_len == 0xffff) - GPG_NO_RECORD (); + { + apdu.res_apdu_data_len = 0; + GPG_NO_RECORD (); + } else /* Add length of (tag+len) */ apdu.res_apdu_data_len += 4; diff --git a/src/usb-icc.c b/src/usb-icc.c index 3d442cb..db21ae8 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -734,17 +734,44 @@ icc_handle_data (void) int len = apdu.res_apdu_data_len; if (apdu.res_apdu_data == NULL) - { /* send last byte of 0x9000 */ - icc_buffer[ICC_MSG_HEADER_SIZE] = 0x00; - len = 1; + { /* send status word(s) of 0x9000 */ + len = 0; + + if (apdu.res_apdu_data_len == 2) + { + icc_buffer[ICC_MSG_HEADER_SIZE] = 0x90; + len++; + } + + icc_buffer[ICC_MSG_HEADER_SIZE+len] = 0x00; + len++; } else if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE]) { - if (apdu.res_apdu_data_len >= ICC_RESPONSE_MSG_DATA_SIZE) + if (apdu.res_apdu_data_len > ICC_RESPONSE_MSG_DATA_SIZE) { memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE); apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE; + apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; + } + else if (apdu.res_apdu_data_len == ICC_RESPONSE_MSG_DATA_SIZE) + { + memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], + apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE); + apdu.res_apdu_data = NULL; + apdu.res_apdu_data_len = 2; + } + else if (apdu.res_apdu_data_len + == ICC_RESPONSE_MSG_DATA_SIZE - 1) + { + memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], + apdu.res_apdu_data, apdu.res_apdu_data_len); + icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] + = 0x90; + apdu.res_apdu_data = NULL; + apdu.res_apdu_data_len = 1; + len += 1; } else if (apdu.res_apdu_data_len <= ICC_RESPONSE_MSG_DATA_SIZE - 2) @@ -756,24 +783,18 @@ icc_handle_data (void) icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1] = 0x00; apdu.res_apdu_data = NULL; + apdu.res_apdu_data_len = 0; len += 2; } - else if (apdu.res_apdu_data_len - == ICC_RESPONSE_MSG_DATA_SIZE - 1) - { - memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], - apdu.res_apdu_data, apdu.res_apdu_data_len); - icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] - = 0x90; - apdu.res_apdu_data = NULL; - len += 1; - } } else - memmove (&icc_buffer[ICC_MSG_HEADER_SIZE], - &icc_buffer[ICC_MSG_HEADER_SIZE] - +ICC_RESPONSE_MSG_DATA_SIZE, - apdu.res_apdu_data_len); + { + memmove (&icc_buffer[ICC_MSG_HEADER_SIZE], + &icc_buffer[ICC_MSG_HEADER_SIZE] + +ICC_RESPONSE_MSG_DATA_SIZE, + apdu.res_apdu_data_len); + apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; + } if (len <= ICC_RESPONSE_MSG_DATA_SIZE) { @@ -781,10 +802,7 @@ icc_handle_data (void) next_state = ICC_STATE_WAIT; } else - { - icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03); - apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; - } + icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03); } else {