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.
ISO 14443
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[0](PC4) high
a Toggle AUX[0](PC4) low
@ Read AUX[0](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.
dnfc2> rf-off-on
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!
Anti-collision sequence
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:
93 | 20 |
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. | CRC A |
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.
93 | 70 | B9CC137117 | CRCA |
Select Cascade Level 1 command | This time we send 7 bytes (without including the CRC_A) | The card UID + BCC | Automatically computed |
We receive the SAK (Select Acknowledge) indicating the anti-collision sequence is finished.
dnfc2> send-auto 9370B9CC137117
20
SAK | CRC A |
20 | Not displayed |
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 🙂 .
FDSI | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Other |
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 computed |
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. |
CRC_A | Not displayed |
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.
What next?
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.