Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/42306?usp=email )
Change subject: ccid: properly emit wait time ext messages ......................................................................
ccid: properly emit wait time ext messages
The CCID message that tells the host that the card asked for a wait time extension was missing.
This is a bit weird, because it breaks the 1:1 relationship between messages and responses that usually exists, nor does it consume a bSeq, so we just count and emit WT msgs as appropriate.
Closes: OS#6458 Change-Id: Ib69483d453a0e5ebb1bc1885a8f78790a0f10d70 --- M ccid_common/ccid_device.h M ccid_common/ccid_slot_fsm.c M ccid_common/iso7816_fsm.c M ccid_common/iso7816_fsm.h 4 files changed, 46 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/06/42306/1
diff --git a/ccid_common/ccid_device.h b/ccid_common/ccid_device.h index 97d6212..ee2b5e2 100644 --- a/ccid_common/ccid_device.h +++ b/ccid_common/ccid_device.h @@ -78,6 +78,8 @@ const struct ccid_pars_decoded *default_pars; volatile uint32_t event; volatile void* event_data; + /* count of pending Wait Time Extension notifications to send to host */ + volatile uint32_t wtime_ext; };
/* CCID operations provided by USB transport layer */ diff --git a/ccid_common/ccid_slot_fsm.c b/ccid_common/ccid_slot_fsm.c index c34ad72..307c50f 100644 --- a/ccid_common/ccid_slot_fsm.c +++ b/ccid_common/ccid_slot_fsm.c @@ -102,6 +102,7 @@ card_uart_ctrl(ss->cuart, CUART_CTL_POWER_5V0, false); cs->icc_powered = false; cs->cmd_busy = false; + cs->wtime_ext = 0; } }
@@ -175,6 +176,10 @@ case ISO7816_E_HW_ERR_IND: card_uart_ctrl(ss->cuart, CUART_CTL_NO_RXTX, true); break; + case ISO7816_E_WTIME_EXT_IND: + /* card sent NULL byte (0x60); notify host via intermediate TimeExtension response */ + cs->wtime_ext++; + break; case ISO7816_E_ATR_ERR_IND: case ISO7816_E_TPDU_FAILED_IND: case ISO7816_E_PPS_FAILED_IND: @@ -206,6 +211,27 @@ volatile uint32_t event = cs->event; volatile void * volatile data = cs->event_data;
+ /* send pending Wait Time Extension notifications to host. + * wtime_ext is incremented from ISR context (UART RX -> FSM -> user_cb), + * so we must atomically read-and-clear to avoid losing increments. */ + if (cs->wtime_ext) { + uint32_t wt_pending; +#ifdef OCTSIMFWBUILD + CRITICAL_SECTION_ENTER(); +#endif + wt_pending = cs->wtime_ext; + cs->wtime_ext = 0; +#ifdef OCTSIMFWBUILD + CRITICAL_SECTION_LEAVE(); +#endif + for (uint32_t i = 0; i < wt_pending; i++) { + LOGPCS(cs, LOGL_DEBUG, "Sending Wait Time Extension to host\n"); + resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_TIME_EXT, 1, NULL, 0); + /* this does neither consume the bSeq nor unbusy the slot! */ + ccid_slot_send(cs, resp); + } + } + if (!event) return 0; // if(event && !data) @@ -224,6 +250,7 @@ resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_FAILED, CCID_ERR_ICC_MUTE, 0, 0); ccid_slot_send_unbusy(cs, resp); cs->event = 0; + cs->wtime_ext = 0; break; case ISO7816_E_ATR_DONE_IND: tpdu = data; @@ -239,6 +266,7 @@ resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, msgb_data(tpdu), msgb_length(tpdu)); ccid_slot_send_unbusy(cs, resp); cs->event = 0; + cs->wtime_ext = 0; break; case ISO7816_E_ATR_ERR_IND: tpdu = data; @@ -252,6 +280,7 @@ resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_FAILED, CCID_ERR_ICC_MUTE, msgb_data(tpdu), msgb_length(tpdu)); ccid_slot_send_unbusy(cs, resp); cs->event = 0; + cs->wtime_ext = 0; break; break; case ISO7816_E_TPDU_DONE_IND: @@ -261,6 +290,7 @@ resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, msgb_l4(tpdu), msgb_l4len(tpdu)); ccid_slot_send_unbusy(cs, resp); cs->event = 0; + cs->wtime_ext = 0; break; case ISO7816_E_TPDU_FAILED_IND: tpdu = data; @@ -275,6 +305,7 @@ resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_FAILED, CCID_ERR_ICC_MUTE, msgb_l2(tpdu), 0); ccid_slot_send_unbusy(cs, resp); cs->event = 0; + cs->wtime_ext = 0; break; case ISO7816_E_PPS_DONE_IND: tpdu = data; @@ -310,6 +341,7 @@ ccid_slot_send_unbusy(cs, resp);
cs->event = 0; + cs->wtime_ext = 0; break; case ISO7816_E_PPS_UNSUPPORTED_IND: /* unsupported means no response, failed means request/response mismatch @@ -331,6 +363,7 @@ ccid_slot_send_unbusy(cs, resp);
cs->event = 0; + cs->wtime_ext = 0; break; case 0: break; diff --git a/ccid_common/iso7816_fsm.c b/ccid_common/iso7816_fsm.c index a035148..c59bc7d 100644 --- a/ccid_common/iso7816_fsm.c +++ b/ccid_common/iso7816_fsm.c @@ -228,6 +228,7 @@ { ISO7816_E_ATR_DONE_IND, "ATR_DONE_IND" }, { ISO7816_E_ATR_ERR_IND, "ATR_ERR_IND" }, { ISO7816_E_TPDU_DONE_IND, "TPDU_DONE_IND" }, + { ISO7816_E_WTIME_EXT_IND, "WTIME_EXT_IND" }, { ISO7816_E_XCEIVE_TPDU_CMD, "XCEIVE_TPDU_CMD" }, /* allstate events */ { ISO7816_E_WTIME_EXP, "WAIT_TIME_EXP" }, @@ -432,6 +433,10 @@ /* hand finished TPDU to user */ ip->user_cb(fi, event, 0, apdu); break; + case ISO7816_E_WTIME_EXT_IND: + /* notify user of wait time extension; TPDU still in progress! */ + ip->user_cb(fi, event, 0, NULL); + break; default: OSMO_ASSERT(0); } @@ -588,7 +593,8 @@ S(ISO7816_E_TX_COMPL) | S(ISO7816_E_RX_ERR_IND) | S(ISO7816_E_TX_ERR_IND) | - S(ISO7816_E_TPDU_DONE_IND), + S(ISO7816_E_TPDU_DONE_IND) | + S(ISO7816_E_WTIME_EXT_IND), .out_state_mask = S(ISO7816_S_RESET) | S(ISO7816_S_WAIT_TPDU) | S(ISO7816_S_IN_TPDU), @@ -1319,6 +1325,7 @@ LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte); if (byte == 0x60) { /* NULL: wait for another procedure byte */ + osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_WTIME_EXT_IND, NULL); card_uart_set_rx_threshold(ip->uart, 1); card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 1); osmo_fsm_inst_state_chg(fi, TPDU_S_PROCEDURE, 0, 0); @@ -1490,6 +1497,7 @@ LOGPFSML(fi, LOGL_DEBUG, "Received 0x%02x from UART\n", byte); if (byte == 0x60) { /* NULL: wait for actual SW1 */ + osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_WTIME_EXT_IND, NULL); card_uart_set_rx_threshold(ip->uart, 1); card_uart_ctrl(ip->uart, CUART_CTL_RX_TIMER_HINT, 1); osmo_fsm_inst_state_chg(fi, TPDU_S_SW1, 0, 0); diff --git a/ccid_common/iso7816_fsm.h b/ccid_common/iso7816_fsm.h index fb37396..542880a 100644 --- a/ccid_common/iso7816_fsm.h +++ b/ccid_common/iso7816_fsm.h @@ -47,6 +47,8 @@ /* TODO: Rx FIFO overrun */ /* TODO: Rx buffer overrun */
+ ISO7816_E_WTIME_EXT_IND, /*!< Wait Time Extension (NULL byte 0x60) from card */ + /* internal events between FSMs in this file */ ISO7816_E_ATR_DONE_IND, /*!< ATR Done indication from ATR child FSM */ ISO7816_E_ATR_ERR_IND, /*!< ATR Error indication from ATR child FSM */