This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Kévin Redon gerrit-no-reply at lists.osmocom.orgKévin Redon has uploaded this change for review. ( https://gerrit.osmocom.org/13949 Change subject: add function to transfer TPDU ...................................................................... add function to transfer TPDU this function takes care of reading and writing the complete TPDU to the card. note: the sim-iccid command uses this function, but still only to select MF. Change-Id: I50c90f3697580a4c93220a3e09cc33ec85889814 --- M sysmoOCTSIM/main.c 1 file changed, 184 insertions(+), 83 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/49/13949/1 diff --git a/sysmoOCTSIM/main.c b/sysmoOCTSIM/main.c index 11849c7..327ac6d 100644 --- a/sysmoOCTSIM/main.c +++ b/sysmoOCTSIM/main.c @@ -226,7 +226,183 @@ // set baud rate uint32_t baudrate = (freq * d) / f; // calculate actual baud rate - return slot_set_baudrate(slotnr, baudrate); // // set baud rate + return slot_set_baudrate(slotnr, baudrate); // set baud rate +} + +/** write data to card + * @param[in] slotnr slot number on which to send data + * @param[in] data data to be transmitted + * @param[in] length length of data to be transmitted + * @return error code + */ +static int slot_card_write(uint8_t slotnr, const uint8_t* data, uint16_t length) +{ + // input checks + ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors)); + if (0 == length || NULL == data) { + return ERR_INVALID_ARG; + } + + struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr]; + ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 0; // disable receive (to avoid the echo back) + SIM_tx_count[slotnr] = false; // reset TX complete + for (uint16_t i = 0; i < length; i++) { // transmit data + while(!usart_async_is_tx_empty(sim)); // wait for previous byte to be transmitted (WARNING blocking) + if (1 != io_write(&sim->io, &data[i], 1)) { // put but in transmit buffer + return ERR_IO; + } + } + while (!SIM_tx_count[slotnr]); // wait until transmission is complete (WARNING blocking) + ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1; // enable receive again + + return ERR_NONE; +} + +/** read data from card + * @param[in] slotnr slot number on which to send data + * @param[out] data buffer for read data to be stored + * @param[in] length length of data to be read + * @param[in] wt Waiting Time in ETU + * @return error code + * TODO fix WT/ETU duration + */ +static int slot_card_read(uint8_t slotnr, uint8_t* data, uint16_t length, uint32_t wt) +{ + // input checks + ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors)); + if (0 == length || NULL == data) { + return ERR_INVALID_ARG; + } + + struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr]; + + ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1; // ensure RX is enabled + uint32_t timeout = wt; // reset waiting time + for (uint16_t i = 0; i < length; i++) { // read all data + while (timeout && !usart_async_is_rx_not_empty(sim)) { // verify if data is present + delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us) + timeout--; + } + if (0 == timeout) { // timeout reached + return ERR_TIMEOUT; + } + timeout = wt; // reset waiting time + if (1 != io_read(&sim->io, &data[i], 1)) { // read one byte + return ERR_IO; + } + } + + return ERR_NONE; +} + +/** transfer TPDU + * @param[in] slotnr slot number on which to transfer the TPDU + * @param[in] header TPDU header to send + * @param[io] data TPDU data to transfer + * @param[in] data_length length of TPDU data to transfer + * @param[in] write if the data should be written (true) or read (false) + * TODO fix WT + * TODO the data length can be deduce from the header + */ +static int slot_tpdu_xfer(uint8_t slotnr, const uint8_t* header, uint8_t* data, uint16_t data_length, bool write) +{ + // input checks + ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors)); + if (NULL == header || (data_length > 0 && NULL == data)) { + return ERR_INVALID_ARG; + } + + int rc; + struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr]; // get USART peripheral + usart_async_flush_rx_buffer(sim); // flush RX buffer to start from scratch + + // send command header + printf("(%d) TPDU: ", slotnr); + for (uint8_t i = 0; i < 5; i++) { + printf("%02x ", header[i]); + } + rc = slot_card_write(slotnr, header, 5); // transmit header + if (ERR_NONE != rc) { + printf("error in command header transmit (errno = %d)\r\n", rc); + return rc; + } + + // read procedure byte, and handle data + uint8_t pb = 0x60; // wait more procedure byte + uint16_t data_i = 0; // progress in the data transfer + while (0x60 == pb) { // wait for SW + rc = slot_card_read(slotnr, &pb, 1, ISO7816_3_DEFAULT_WT); + if (ERR_NONE != rc) { + printf("error while receiving PB/SW1 (errno = %d)\r\n", rc); + return rc; + } + printf("%02x ", pb); + if (0x60 == pb) { // NULL byte + // just wait more time + } else if ((0x60 == (pb & 0xf0)) || (0x90 == (pb & 0xf0))) { // SW1 byte + // left the rest of the code handle it + } else if (header[1] == pb) { // ACK byte + // transfer rest of the data + if (data_i >= data_length) { + printf("error no more data to transfer\r\n"); + return ERR_INVALID_DATA; + } + if (write) { // transmit remaining command data + rc = slot_card_write(slotnr, &data[data_i], data_length - data_i); // transmit command data + if (ERR_NONE != rc) { + printf("error in command data transmit (errno = %d)\r\n", rc); + return rc; + } + } else { // receive remaining command data + rc = slot_card_read(slotnr, &data[data_i], data_length - data_i, ISO7816_3_DEFAULT_WT); + if (ERR_NONE != rc) { + printf("error in command data receive (errno = %d)\r\n", rc); + return rc; + } + } + for (uint16_t i = data_i; i < data_length; i++) { + printf("%02x ", data[i]); + } + data_i = data_length; // remember we transferred the data + pb = 0x60; // wait for SW1 + } else if (header[1] == (pb ^ 0xff)) { // ACK byte + // transfer only one byte + if (data_i >= data_length) { + printf("error no more data to transfer\r\n"); + return ERR_INVALID_DATA; + } + if (write) { // transmit command data byte + rc = slot_card_write(slotnr, &data[data_i], 1); // transmit command data + if (ERR_NONE != rc) { + printf("error in command data transmit (errno = %d)\r\n", rc); + return rc; + } + } else { // receive command data byte + rc = slot_card_read(slotnr, &data[data_i], 1, ISO7816_3_DEFAULT_WT); + if (ERR_NONE != rc) { + printf("error in command data receive (errno = %d)\r\n", rc); + return rc; + } + } + printf("%02x ", data[data_i]); + data_i += 1; // remember we transferred one data byte + pb = 0x60; // wait for SW1 + } else { // invalid byte + return ERR_INVALID_DATA; + } + } + + // read SW2 + uint8_t sw2; + rc = slot_card_read(slotnr, &sw2, 1, ISO7816_3_DEFAULT_WT); + if (ERR_NONE != rc) { + printf("error in receiving SW2 (errno = %d)\r\n", rc); + return rc; + } + printf("%02x", sw2); + + printf("\r\n"); + return ERR_NONE; } DEFUN(sim_status, cmd_sim_status, "sim-status", "Get state of specified NCN8025") @@ -480,90 +656,15 @@ ncn8025_set(slotnr, &settings); } - // read MF - printf("(%d) SELECT MF: ", slotnr); - struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr]; - ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 0; - usart_async_flush_rx_buffer(sim); // flush RX buffer to start from scratch + // select MF + printf("(%d) SELECT MF\r\n", slotnr); // write SELECT MF APDU - const uint8_t select_mf[] = {0xa0, 0xa4, 0x00, 0x00, 0x02, 0x3f, 0x00}; - SIM_tx_count[slotnr] = false; // reset TX complete - for (uint8_t i = 0; i < 5; i++) { // transmit command header - printf("%02x ", select_mf[i]); - while(!usart_async_is_tx_empty(sim)); // wait for previous byte to be transmitted (WARNING could block) - if (1 != io_write(&sim->io, &select_mf[i], 1)) { - printf("(%d) error: could not send command header\r\n", slotnr); - return; - } + const uint8_t select_mf_header[] = {0xa0, 0xa4, 0x00, 0x00, 0x02}; + const uint8_t select_mf_data[] = {0x3f, 0x00}; + int rc = slot_tpdu_xfer(slotnr, select_mf_header, (uint8_t*)select_mf_data, ARRAY_SIZE(select_mf_data), true); // transfer TPDU + if (ERR_NONE != rc) { + printf("error while SELECT MF (errno = %d)\r\n", rc); } - uint16_t wt = ISO7816_3_DEFAULT_WT; // waiting time in ETU (actually it can be a lot more after the ATR, but we use the default) - while (wt && !SIM_tx_count[slotnr]) { // wait until transmission is complete - delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us) - wt--; - } - if (0 == wt) { // timeout reached - printf("(%d) error: could not transmit data\r\n", slotnr); - return; - } - ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1; - //usart_async_flush_rx_buffer(sim); // flush RX buffer to start from scratch - wt = ISO7816_3_DEFAULT_WT; // reset waiting time - while (wt && !usart_async_is_rx_not_empty(sim)) { // wait for procedure byte - delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us) - wt--; - } - if (0 == wt) { // timeout reached - printf("(%d) error: card not responsive\r\n", slotnr); - return; - } - uint8_t pb; - if (1 != io_read(&sim->io, &pb, 1)) { // read procedure byte - printf("(%d) error: could not read data\r\n", slotnr); - return; - } - if (select_mf[1] != pb) { // the header is ACKed when the procedure by is equal to the instruction byte - printf("(%d) error: header NACKed\r\n", slotnr); - return; - } - SIM_tx_count[slotnr] = false; // reset TX complete - for (uint8_t i = 5; i < 7; i++) { // transmit command data - printf("%02x ", select_mf[i]); - while(!usart_async_is_tx_empty(sim)); // wait for previous byte to be transmitted (WARNING could block) - if (1 != io_write(&sim->io, &select_mf[i], 1)) { - printf("(%d) error: could not send command data\r\n", slotnr); - return; - } - } - wt = ISO7816_3_DEFAULT_WT; // waiting time in ETU (actually it can be a lot more after the ATR, but we use the default) - while (wt && !SIM_tx_count[slotnr]) { // wait until transmission is complete - delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us) - wt--; - } - if (0 == wt) { // timeout reached - printf("(%d) error: could not transmit data\r\n", slotnr); - return; - } - usart_async_flush_rx_buffer(sim); // flush RX buffer to start from scratch - // read SW - uint8_t sw[2]; // to read the status words - wt = ISO7816_3_DEFAULT_WT; // waiting time in ETU (actually it can be a lot more after the ATR, but we use the default) - for (uint8_t i = 0; i < ARRAY_SIZE(sw); i++) { - while (wt && !usart_async_is_rx_not_empty(sim)) { - delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us) - wt--; - } - if (0 == wt) { // timeout reached - printf("(%d) error: card not responsive\r\n", slotnr); - } else { - if (1 != io_read(&sim->io, &sw[i], 1)) { // read SW - printf("(%d) error: could not read data\r\n", slotnr); - return; - } - printf("%02x ", sw[i]); - wt = ISO7816_3_DEFAULT_WT; // reset WT - } - } - printf("\r\n"); // disable LED settings.led = false; -- To view, visit https://gerrit.osmocom.org/13949 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-ccid-firmware Gerrit-Branch: master Gerrit-MessageType: newchange Gerrit-Change-Id: I50c90f3697580a4c93220a3e09cc33ec85889814 Gerrit-Change-Number: 13949 Gerrit-PatchSet: 1 Gerrit-Owner: Kévin Redon <kredon at sysmocom.de> -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20190509/1cdf30cb/attachment.htm>