In short, this post explains how to initialize an ISO 14443-A smart card with short or standard frame thanks to the hydra NFC v2 console. Straightforwardly, you will be able to send correct commands or ill-formed command to fuzz a card. In a next post, we will see how to initialize an ISO 14443-B smart card and how to build TPDUs commands.
In a previous post, we saw how to connect automatically to a smart card, and then exchange APDUs commands. But, how to initialize a card and what is the communication protocol used to transmit the APDU? In this post, we will focus on the ISO 14443 norm since most of the banking smart cards use it (as well electronic passport). More especially, we will talk about the initialization of an ISO 14443-A card with the Hydra NFC v2 console.
Within this norm, a card can be the A or the B type. Four parts explain it:
- ISO 14443 Part 1 & 2.
- It explains how the signal must be modulated. We won’t talk about it in this post.
- ISO 14443 Part 3.
- It defines the initialization sequence which is different between type A & B.
- It explains how a communication frame must be built.
- ISO 14443 Part 4. It defines the transmission protocol based on the Transport Data Protocol Unit (TPDU) which is common to type A & B:
- It details initialization commands for instance when the card indicates its communication capacity (communication speed, block size), and the reader can indicate which one to use.
- How to exchange data thanks to the TPDUs.
ISO 14443-A Initialization sequence
We connect with picocom (but you could use putty as well).
$ picocom -b 115200 /dev/ttyACM0 Type [C-a] [C-h] to see available commands Terminal ready >
This time, we don’t enter in “nfc” menu, but in “dnfc”.
> dnfc HydraNFC Shield v2 initialized with success. Device: SPI2 GPIO resistor: floating Mode: master Frequency: 10.50mhz (160khz, 320khz, 650khz, 1.31mhz, 2.62mhz, 5.25mhz, 21mhz) Polarity: 0 Phase: 1 Bit order: MSB first
If we type “help”, we see there is a lot of commands! This menu can be considered as the low-level command sandbox . Don’t worry, we will not use all the commands!
dnfc2> help Configuration: spi2 [frequency (value hz/khz/mhz)] Interaction: [cs-on/cs-off] <read/write (value:repeat)> [exit] show Show DNFCv2 parameters frequency Set SPI Bus frequency trigger Setup DNFCv2 SPI2 trigger set-nfc-mode Set NFC Mode and TX/RX BitRate in kbit/s get-nfc-mode Get NFC Mode rf-off-on Set RF field off/on reqa Send ISO 14443-A REQA wupa Send ISO 14443-A WUPA send Send bytes according to the selected mode send-auto Send bytes according to the selected mode and add the two-bytes CRC nfc-transp Enter NFC Transparent Mode nfc-stream Enter NFC Stream Mode read SPI Read byte (repeat with :<num>) hd SPI Read byte (repeat with :<num>) and print hexdump write SPI Write byte (repeat with :<num>) <integer> SPI Write byte (repeat with :<num>) <string> SPI Write string cs-on SPI Alias for "chip-select on" cs-off SPI Alias for "chip-select off" [ SPI Alias for "chip-select on" ] SPI Alias for "chip-select off" & Delay 1 usec (repeat with :<num>) % Delay 1 msec (repeat with :<num>) ~ SPI Write a random byte (repeat with :<num>) A Toggle AUX(PC4) high a Toggle AUX(PC4) low @ Read AUX(PC4) exit Exit DNFCv2 mode
Let see the “set-nfc-mode” command.
dnfc2> help set-nfc-mode Set NFC Mode and TX/RX BitRate in kbit/s nfc-mode Set NFC Mode POLL_NFCA=1, POLL_NFCA_T1T=2, POLL_NFCB=3, POLL_B_PRIME=4, POLL_B_CTS=5, POLL_NFCF=6, POLL_NFCV=7 POLL_PICOPASS=8, POLL_ACTIVE_P2P=9, LISTEN_NFCA=10, LISTEN_NFCB=11, LISTEN_NFCF=12, LISTEN_ACTIVE_P2P=13 nfc-mode-tx_br Set TX BitRate BR_106=0, BR_212=1, BR_424=2, BR_848=3, BR_52p97=235, BR_26p48=236, BR_1p66=237 nfc-mode-rx_br Set RX BitRate BR_106=0, BR_212=1, BR_424=2, BR_848=3, BR_52p97=235, BR_26p48=236, BR_1p66=237
We select ISO 14443-A type: the reader will send data with the modulation required by the type A. We keep the default bitrate for transmission and reception.
dnfc2> set-nfc-mode nfc-mode 1 nfc-mode = 1 nfc-mode-tx_br = 0 nfc-mode-rx_br = 0 rfalSetMode OK
We deactivate/activate the RF field to restart our card.
First, the REQA command is sent to detect a card. It is a short frame meaning only 7 coding bits are sent. To ease your understanding, we will not talk about the “protocol bits” in this post, as the start/stop bits and so on. The REQA value is 0x26.
dnfc2> reqa 04 00
Our card is detected since we receive a response: the Answer To Request, named ATQA!
Once a card was detected, we must execute an anti-collision sequence to select it: the reader asks the card UID, and then send it back to confirm that it wants to talk with it. Another aim of this sequence is to be able to correctly select a specific card when several cards answered the REQA. We will not cover this case, and consider that only one card was detected.
Now, the communication is based on a standard frame, meaning packet of full bytes (ie 8 bits) are sent. Most of the time, a two-byte Cyclic Redundancy Check error code is added at the end of the data to check their integrity. It is specific to the type A, so we named it CRC_A. It is defined in ISO/IEC 13239. Once again, we make a little approximation about the standard frame, it means we do not take about the start/end bit, as well the parity bit. We just talk about coding bit.
First, we send the Select Cascade Level 1 command:
|Select Cascade Level 1 command||The high nibble 2 means we send 2 bytes. The low nibble means we add 0 bits in the command. For instance, if the value was 23, it means we would send 2*8 + 3 = 11 bits.|
We use the send command to communicate them to the card. This command sends only the given bytes according to the selected mode.
dnfc2> send 9320 B9 CC 13 71 17
We received the first 4 UID bytes of the card.
|Card UID||BCC. It corresponds to the xor |
of the 4 previous bytes.
|B9 CC 13 71||17||Hum… Nothing, because we do not |
display it for the moment :). We will
add an option to display it or not.
Now, we send back a Select Cascade Level 1 command with the UID to indicate that we want to select this card. This time, we must add a CRC_A in the command. To avoid computing yourself the CRC, you can use the send-auto command that will automatically compute and add the CRC according to the selected mode.
|Select Cascade Level 1 command||This time we send|
7 bytes (without including the
|The card UID + BCC||Automatically|
We receive the SAK (Select Acknowledge) indicating the anti-collision sequence is finished.
dnfc2> send-auto 9370B9CC137117 20
The third bit of the SAK equals 0: it means we received the full card UID. In fact, it size could be 4, 7 or 10 bytes. In this case, we shall have used Select Cascade Level 2 or 3 commands.
Request for answer to select (RATS)
Ok, so the reader and the card agreed to talk together. Now, the reader can inform the card about its communication preferences with the RATS command. It enables to indicate to the card:
- the Frame Size for proximity coupling Device Integer (FSDI) (high nibble). This integer indicates the maximum frame size that we’ll be sent by the reader (Frame Size for proximity coupling Device or FSD). It is typically the thing you would like to set to its lowest value, and then send a frame with a bigger value 🙂 .
|FSD (in bytes)||16||24||32||40||48||64||96||128||256||RFU|
- the CID. It enables to indicate the channel number. We set it to 0.
|Start byte||Parameter||CRC A|
|E0||00 (High nibble: FSDI, low nibble CID)||Automatically|
We send the command.
dnfc2> send-auto E000 0A 78 80 82 02 20 63 CB A3 A0
The card answers with the Answer to select (ATS) its communication options: its frame size, the presence of specific bytes, communication speed…
|0A||Length of the full command (this byte included) without the CRC_A|
|78||7: Bytes TA1/TB1/TC1 transmitted|
8: FSCI. It is like the FDSI but for the card. So, it tells the reader that it can send up to 256 bytes.
|80||TA1. It indicates the card supported communication speed.|
|82||TB1. It deals with delay between the frames.|
|02||TC1. It indicates if optional byte will be present in the TPDU header.|
|20 63 CB A3 A0||Historical bytes. It can gives other information about the card.|
Protocol and parameter selection request (PPS)
Finally, the reader can send a PPS to customize the communication speed. We send here a default value where no modification is done (and the speed modification is not implemented in this command).
dnfc2> send-auto D001 D0
The card acknowledges our parameters. And now, we are ready to send TPDUs!
In fact, all the initialization sequence was done automatically done with the connect command that we saw in the previous post. Do you remember?
> nfc NFCv2> connect > 26 < 04 00 > 93 20 < B9 CC 13 71 17 > 93 70 B9 CC 13 71 17 < 20 > E0 00 < 0A 78 80 82 02 20 63 CB A3 A0 > D0 01 < D0 ISO 14443-A card detected.
Another fun fact, the ISO 14443-A norm is used for the electronic passport. If you try to connect twice to your passport for instance with the connect command in the nfc menu, you will see the UID is not the same:
NFCv2> connect > 26 < 04 00 > 93 20 < 08 99 8B 85 9F [Line removed...] NFCv2> connect > 26 < 04 00 > 93 20 < 08 46 13 2C 71 [Line removed...] NFCv2>
It is weird. First time, the card UID is 99 8B 85 9F, and the second time it is 46 13 2C 71. A card UID is supposed be static, no? Yes, but for anonymity reason, and to prevent tracing someone with its ePassport UID, it is mandatory that the returned value is random.
We saw that we can perform the initialization sequence of an ISO 14443-A card within the Hydra NFC v2 menu:
- We can send short frame like the REQA.
- We can send raw standard frame, with or without the automatic computation of the CRC_A. So, you can send correct frame, or random data to fuzz the card.
In a next post, we will send:
- How to initialize an ISO 14443-B smartcards.
- How to build TPDUs.
- And how to script all these commands with Python.