From cf463f29cd9fcfefb7f687c8091b9c0681e30dea Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 11 Jan 2011 09:16:40 +0900 Subject: [PATCH] workaround for libccid 1.3.11 --- ChangeLog | 6 +++ src/gnuk.h | 1 - src/usb-icc.c | 127 ++++++++++++++++++++++++++++++-------------------- 3 files changed, 82 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index 54e5296..9b6ec38 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-01-08 NIIBE Yutaka + + * src/usb-icc.c (icc_handle_data): Handle the case of + ICC_STATE_SEND (back again to the implementation of v0.4). + (USBthread): Don't send back larger block (for libccid 1.3.11). + 2011-01-07 NIIBE Yutaka * src/openpgp.c (cmd_read_binary): Call gpg_do_get_data for AID. diff --git a/src/gnuk.h b/src/gnuk.h index 19e2c1f..67cbf2f 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -54,7 +54,6 @@ enum icc_state /* Busy1, Busy2, Busy3, Busy5 */ ICC_STATE_EXECUTE, /* Busy4 */ ICC_STATE_RECEIVE, /* APDU Received Partially */ - /* Not used */ ICC_STATE_SEND, /* APDU Sent Partially */ }; diff --git a/src/usb-icc.c b/src/usb-icc.c index 471bc6a..7f08b11 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -389,29 +389,35 @@ icc_power_off (void) int res_APDU_size; static void -icc_send_data_block_filling_header (int len) +icc_send_data_block (int len, uint8_t status, uint8_t chain) { int tx_size = USB_LL_BUF_SIZE; - uint8_t *p = icc_buffer; + uint8_t *p; - icc_buffer[0] = ICC_DATA_BLOCK_RET; - icc_buffer[1] = len & 0xFF; - icc_buffer[2] = (len >> 8)& 0xFF; - icc_buffer[3] = (len >> 16)& 0xFF; - icc_buffer[4] = (len >> 24)& 0xFF; - icc_buffer[5] = 0x00; /* Slot */ - icc_buffer[ICC_MSG_SEQ_OFFSET] = icc_seq; - icc_buffer[ICC_MSG_STATUS_OFFSET] = 0; - icc_buffer[ICC_MSG_ERROR_OFFSET] = 0; - icc_buffer[ICC_MSG_CHAIN_OFFSET] = 0; + if (icc_chain_p) + p = icc_chain_p; + else + p = icc_buffer; + + p[0] = ICC_DATA_BLOCK_RET; + p[1] = len & 0xFF; + p[2] = (len >> 8)& 0xFF; + p[3] = (len >> 16)& 0xFF; + p[4] = (len >> 24)& 0xFF; + p[5] = 0x00; /* Slot */ + p[ICC_MSG_SEQ_OFFSET] = icc_seq; + p[ICC_MSG_STATUS_OFFSET] = status; + p[ICC_MSG_ERROR_OFFSET] = 0; + p[ICC_MSG_CHAIN_OFFSET] = chain; icc_tx_size = ICC_MSG_HEADER_SIZE + len; - icc_next_p = icc_buffer + USB_LL_BUF_SIZE; - if (icc_next_p > &icc_buffer[icc_tx_size]) + if (icc_tx_size < USB_LL_BUF_SIZE) { icc_next_p = NULL; - tx_size = &icc_buffer[icc_tx_size] - p; + tx_size = icc_tx_size; } + else + icc_next_p = p + USB_LL_BUF_SIZE; USB_SIL_Write (EP1_IN, p, tx_size); SetEPTxValid (ENDP1); @@ -420,37 +426,6 @@ icc_send_data_block_filling_header (int len) #endif } -static void -icc_send_data_block (uint8_t status, uint8_t chain) -{ - uint8_t *icc_reply; - - if (icc_chain_p) - icc_reply = icc_chain_p; - else - icc_reply = icc_buffer; - - icc_reply[0] = ICC_DATA_BLOCK_RET; - icc_reply[1] = 0x00; - icc_reply[2] = 0x00; - icc_reply[3] = 0x00; - icc_reply[4] = 0x00; - icc_reply[5] = 0x00; /* Slot */ - icc_reply[ICC_MSG_SEQ_OFFSET] = icc_seq; - icc_reply[ICC_MSG_STATUS_OFFSET] = status; - icc_reply[ICC_MSG_ERROR_OFFSET] = 0x00; - icc_reply[ICC_MSG_CHAIN_OFFSET] = chain; - - icc_next_p = NULL; /* This is a single transaction Bulk-IN */ - icc_tx_size = ICC_MSG_HEADER_SIZE; - USB_SIL_Write (EP1_IN, icc_reply, icc_tx_size); - SetEPTxValid (ENDP1); -#ifdef DEBUG_MORE - DEBUG_INFO ("DATA\r\n"); -#endif -} - - static void icc_send_params (void) { @@ -481,6 +456,8 @@ icc_send_params (void) #endif } +/* Supporting smaller buffer of libccid (<= 1.3.11) */ +#define ICC_RESPONSE_MSG_DATA_SIZE 262 static enum icc_state icc_handle_data (void) @@ -526,7 +503,7 @@ icc_handle_data (void) else if (icc_header->param == 1) { icc_chain_p = icc_next_p; - icc_send_data_block (0, 0x10); + icc_send_data_block (0, 0, 0x10); next_state = ICC_STATE_RECEIVE; } else @@ -603,6 +580,44 @@ icc_handle_data (void) icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); } break; + case ICC_STATE_SEND: + if (icc_header->msg_type == ICC_POWER_OFF) + next_state = icc_power_off (); + else if (icc_header->msg_type == ICC_SLOT_STATUS) + icc_send_status (); + else if (icc_header->msg_type == ICC_XFR_BLOCK) + { + if (icc_header->param == 0x10) + { + memmove (res_APDU, res_APDU+ICC_RESPONSE_MSG_DATA_SIZE, + res_APDU_size); + if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE) + { + icc_send_data_block (res_APDU_size, 0, 0x02); + next_state = ICC_STATE_WAIT; + } + else + { + icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03); + res_APDU_size -= ICC_MAX_MSG_DATA_SIZE; + } + } + else + { + DEBUG_INFO ("ERR0A\r\n"); + DEBUG_BYTE (icc_header->param >> 8); + DEBUG_BYTE (icc_header->param & 0xff); + icc_error (ICC_OFFSET_PARAM); + next_state = ICC_STATE_WAIT; + } + } + else + { + DEBUG_INFO ("ERR06\r\n"); + DEBUG_BYTE (icc_header->msg_type); + icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); + next_state = ICC_STATE_WAIT; + } default: next_state = ICC_STATE_START; DEBUG_INFO ("ERR10\r\n"); @@ -620,7 +635,7 @@ icc_handle_timeout (void) switch (icc_state) { case ICC_STATE_EXECUTE: - icc_send_data_block (ICC_CMD_STATUS_TIMEEXT, 0); + icc_send_data_block (0, ICC_CMD_STATUS_TIMEEXT, 0); break; default: break; @@ -654,8 +669,17 @@ USBthread (void *arg) { if (icc_state == ICC_STATE_EXECUTE) { - icc_send_data_block_filling_header (res_APDU_size); - icc_state = ICC_STATE_WAIT; + if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE) + { + icc_send_data_block (res_APDU_size, 0, 0); + icc_state = ICC_STATE_WAIT; + } + else + { + icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x01); + res_APDU_size -= ICC_RESPONSE_MSG_DATA_SIZE; + icc_state = ICC_STATE_SEND; + } } else { /* XXX: error */ @@ -664,7 +688,8 @@ USBthread (void *arg) } else if (m == EV_TX_FINISHED) { - if (icc_state == ICC_STATE_START || icc_state == ICC_STATE_WAIT) + if (icc_state == ICC_STATE_START || icc_state == ICC_STATE_WAIT + || icc_state == ICC_STATE_SEND) icc_prepare_receive (0); else if (icc_state == ICC_STATE_RECEIVE) icc_prepare_receive (1);