Change in osmo-ccid-firmware[master]: add debug command to communicate with card

Kévin Redon gerrit-no-reply at lists.osmocom.org
Thu May 9 13:33:10 UTC 2019


Kévin Redon has uploaded this change for review. ( https://gerrit.osmocom.org/13943


Change subject: add debug command to communicate with card
......................................................................

add debug command to communicate with card

currently the read-iccid command only selects MF.
this is a proof of concept for card communication.
the transmission/reception must be generalized to avoid copying
the code multiple times.

Change-Id: Icbcde783143694afce23af6e3f26bcd7a9a13b85
---
M sysmoOCTSIM/main.c
1 file changed, 145 insertions(+), 7 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/43/13943/1

diff --git a/sysmoOCTSIM/main.c b/sysmoOCTSIM/main.c
index a895c14..11849c7 100644
--- a/sysmoOCTSIM/main.c
+++ b/sysmoOCTSIM/main.c
@@ -38,10 +38,28 @@
 // TODO for now SIM7 is not present because used for debug
 static struct usart_async_descriptor* SIM_peripheral_descriptors[] = {&SIM0, &SIM1, &SIM2, &SIM3, &SIM4, &SIM5, &SIM6, NULL};
 
+/** number of bytes transmitted on the SIM peripheral */
+static volatile bool SIM_tx_count[8];
+
 static void SIM_rx_cb(const struct usart_async_descriptor *const io_descr)
 {
 }
 
+/** called when the transmission is complete
+ *  e.g. this is when the byte has been sent and there is no data to transmit anymore
+ */
+static void SIM_tx_cb(const struct usart_async_descriptor *const io_descr)
+{
+	// find slotnr for corresponding USART
+	uint8_t slotnr;
+	for (slotnr = 0; slotnr < ARRAY_SIZE(SIM_peripheral_descriptors) && SIM_peripheral_descriptors[slotnr] != io_descr; slotnr++);
+
+	// set flag
+	if (slotnr < ARRAY_SIZE(SIM_peripheral_descriptors)) {
+		SIM_tx_count[slotnr] = true;
+	}
+}
+
 /** possible clock sources for the SERCOM peripheral
  *  warning: the definition must match the GCLK configuration
  */
@@ -80,6 +98,7 @@
 			continue;
 		}
 		usart_async_register_callback(SIM_peripheral_descriptors[i], USART_ASYNC_RXC_CB, SIM_rx_cb); // required for RX to work, even if the callback does nothing
+		usart_async_register_callback(SIM_peripheral_descriptors[i], USART_ASYNC_TXC_CB, SIM_tx_cb); // to count the number of bytes transmitted since we are using it asynchronously
 		usart_async_enable(SIM_peripheral_descriptors[i]);
 	}
 }
@@ -360,7 +379,7 @@
 	// check if card is present (and read current settings)
 	ncn8025_get(slotnr, &settings);
 	if (!settings.simpres) {
-		printf("no card present in slot %d, aborting\r\n", slotnr);
+		printf("(%d) error: no card present\r\n", slotnr);
 		return;
 	}
 
@@ -406,19 +425,19 @@
 	}
 	// verify if one byte has been received
 	if (!usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {
-		printf("card in slot %d is not responding, aborting\r\n", slotnr);
+		printf("(%d) error: card not responsive\r\n", slotnr);
 		return;
 	}
 
 	// read ATR (just do it until there is no traffic anymore)
-	// TODO the ATR should be parsed to read the right number of bytes
+	// TODO the ATR should be parsed to read the right number of bytes, instead we just wait until to end of WT
 	printf("(%d) ATR: ", slotnr);
 	uint8_t atr_byte;
 	while (usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {
 		if (1 == io_read(&SIM_peripheral_descriptors[slotnr]->io, &atr_byte, 1)) {
 			printf("%02x ", atr_byte);
 		}
-		uint16_t wt = 9600; // waiting time in ETU
+		uint16_t wt = ISO7816_3_DEFAULT_WT; // waiting time in ETU
 		while (wt && !usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {
 			delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)
 			wt--;
@@ -426,9 +445,127 @@
 	}
 	printf("\r\n");
 
-	/* disable VCC and LED, re-enable RST */
-	settings.cmdvcc = false;
-	settings.rstin = true;
+	/* disable LED */
+	settings.led = false;
+	ncn8025_set(slotnr, &settings);
+}
+
+DEFUN(sim_iccid, cmd_sim_iccid, "sim-iccid", "Read ICCID from SIM card")
+{
+	struct ncn8025_settings settings;
+	int slotnr = validate_slotnr(argc, argv, 1);
+
+	if (slotnr < 0 || slotnr >= ARRAY_SIZE(SIM_peripheral_descriptors) || NULL == SIM_peripheral_descriptors[slotnr]) {
+		return;
+	}
+
+	// read current settings and check if card is present and powered
+	ncn8025_get(slotnr, &settings);
+	if (!settings.simpres) {
+		printf("(%d) error: no card present\r\n", slotnr);
+		return;
+	}
+	if (!settings.cmdvcc) {
+		printf("(%d) error: card not powered\r\n", slotnr);
+		return;
+	}
+	if (settings.rstin) {
+		printf("(%d) error: card under reset\r\n", slotnr);
+		return;
+	}
+
+	// enable LED
+	if (!settings.led) {
+		settings.led = true;
+		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
+	// 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;
+		}
+	}
+	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;
 	ncn8025_set(slotnr, &settings);
 }
@@ -450,6 +587,7 @@
 	command_register(&cmd_sim_voltage);
 	command_register(&cmd_sim_led);
 	command_register(&cmd_sim_atr);
+	command_register(&cmd_sim_iccid);
 	testmode_init();
 
 	printf("\r\n\r\nsysmocom sysmoOCTSIM\r\n");

-- 
To view, visit https://gerrit.osmocom.org/13943
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: Icbcde783143694afce23af6e3f26bcd7a9a13b85
Gerrit-Change-Number: 13943
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/29c931e0/attachment-0001.html>


More information about the gerrit-log mailing list