Topic: Passive target mode initialization *without* secondary reader

Having experimented with the SCM SCL3710 dongle (bearing PN531 v4.2) I have found a workaround for the passive target mode initialization. In the approach described hereafter, it is not necessary to use the secondary “starting” reader for establishing the transparent target mode communication channel (used e.g. in nfc-emulate.c).

Well, regarding the anticollision emulation, there is still a problem with the communication speed (cf. here). On the other hand, I guess that removing the “starting” reader obstacle is worth it anyway. It can, for instance, serve as further inspiration for those approaches based on using high-speed communication interfaces of PN53x to speed up the anti-collision response (cf. here).

The alternative approach is based on direct register modification of the contactless unit of the PN531 controller. I call it DRH – Direct Register Hack method. There are two major steps:

1) issue a “dummy” TgInitTAMATargert command (D4 8C),
2) perform several direct register setups using the WriteRegister command (D4 08).

The first step ensures proper context clean up including (possible) certain internal variables of the embedded C51 core firmware. Without this step, the method did not work correctly if e.g. the dongle was configured in initiator mode before. It is important to say this is really a “dummy” command – we do not have to wait for its completion. In fact, it never completes without the secondary reader. The reset being desired, however, is done right at the start. What follows is running the anti-collision microcode command of the internal CL unit. Since we do not expect this will ever succeed, we directly continue with step two. Note that issuing the first WriteRegister command automatically cancels the still running “dummy” TgInitTAMATarget.

The second step ensures manual setup of those relevant registers of the internal CL unit. Finally, it starts the Transceive CL unit microcode, leaving the whole NFC controller in approximately the same state as it would be after a successful TgInitTAMATarget.

Long story short, the following procedure describes all necessary details. Note that issuing strictly “dummy” TgInitTAMATarget with libnfc would require a bit more coding. Since the aim of this demonstration was to experimentally enhance nfc-emulate.c in the simplest way, I decide to stand the implicit 30 seconds USB timeout enforced by pn53x_usb_transceive().

/* performs alternative target init */
bool target_init_alt2(nfc_device_t *pnd) {
  bool r = true;
/* 
*  Issue standard TgInitTAMATarget cmd (encapsulated in nfc_target_init()).
*  This gives a chance to use secondary starting reader.
*  If not successfull, the command will at least reset the PN53x context.
*  IMPORTANT: The context reset is neccessary, therefore this command
*  must NOT be omitted even if secondary reader is not considered!
*  It can be, however, issued directly, without the standard timeout then.
*  Direct issuing is effective and elegant, but the code is then dependent
*  on the particular transport layer (libusb, pcsc, etc.) used. Therefore,
*  it cannot be written in such a simple way like this demo.
*/
  printf("[+] Performing an enhanced passive target mode initialization.\n");
  printf("[+] Now, you can use secondary reader to break the anti-collision.\n");
  printf("[+] To do so, please send e.g. RATS after the anti-collision(select).\n");
  printf("[+] ...for the alternative init, please do nothing - just wait for the timeout.\n");
  if (nfc_target_init(pnd,abtRecv,&szRecvBits)) {
    printf("[+] Target mode successfully started.\n");
    printf("[+] Received initiator command: ");
    print_hex_bits(abtRecv,szRecvBits);
    return true;
  }
/*
  *  Well, the standard initialization has obviously failed.
  *  Nevermind - we will enforce the passive target mode by
  *  the direct register hack (DRH) method instead.
*/
  printf("[+] Secondary reader not met - performing DRH alternative setup.\n");
  // INITIALLY - Stop eventual running CL unit microcode command
  r *= pn53x_set_reg(pnd, 0x6331, 0x3f, 0x00);
  // Configure WaterLevel
  r *= pn53x_set_reg(pnd, 0x633b, 0x7f, 0x3a);
  // Configure Diverse Control
  r *= pn53x_set_reg(pnd, 0x633c, 0x7f, 0x00);
  // Configure TxMode, preserve TxCRCEn flag 
  r *= pn53x_set_reg(pnd, 0x6302, 0x7f, 0x00);
  // Configure RxMode, preserve RxCRCEn flag
  r *= pn53x_set_reg(pnd, 0x6303, 0x7f, 0x00);
  // Configure TxAuto 
  r *= pn53x_set_reg(pnd, 0x6305, 0xef, 0x00);
  // Configure RxThreshold
  r *= pn53x_set_reg(pnd, 0x6308, 0xf7, 0x85);
  // Configure Demod 
  r *= pn53x_set_reg(pnd, 0x6309, 0xef, 0x61);
  // Configure GsNLoadMod 
  r *= pn53x_set_reg(pnd, 0x6313, 0xff, 0x6f);
  // Configure RFCfg
  r *= pn53x_set_reg(pnd, 0x6316, 0xff, 0x59);
  // Configure GsN
  r *= pn53x_set_reg(pnd, 0x6317, 0xff, 0xf4);
  // Configure CWGsP
  r *= pn53x_set_reg(pnd, 0x6318, 0x3f, 0x3f);
  // Configure ModGsP
  r *= pn53x_set_reg(pnd, 0x6319, 0x3f, 0x30);
  // Configure TMode
  r *= pn53x_set_reg(pnd, 0x631a, 0xff, 0x00);
  // FINALLY - Start Transceive CL unit microcode command
  r *= pn53x_set_reg(pnd, 0x6331, 0x3f, 0x0c);
  if (!r) {
    printf("[+] DRH failed!\n");
    return false;
  }
  printf("[+] Done, welcome to the passive target mode.\n");
  // Force REG_CIU_BIT_FRAMING update before next Tx
  pnd->ui8TxBits = 255;

  return r;
}

The aforesaid snippet is rather a simple illustrative procedure. At first, it tries to use the classic (i.e. with the secondary “starting” reader) target mode setup. If it fails (nfc_target_init() times out – other possible failures of nfc_target_init() are neglected here), the alternative DRH approach is used.

The complete version of the patched nfc-emulate.c can be downloaded here. It was successfully tested with SCM SCL3710 dongle bearing PN531 v4.2 and libnfc 1.3.4 under Ubuntu 9.04 with kernel 2.6.28-19-generic. Simply put this code into src/examples and recompile it (e.g. make clean; make all).

Future research
The DRH method was discovered by simply comparing PN531 registers snapshots taken in several important states (after reset, after successful/unsuccessful TgInitTAMATarger, during transparent target mode communication, etc.). Actually, I have taken quite a lot of samples to see which register states are constant (and probably important) and which ones are rather transient (and hence probably unimportant). This simple idea may serve as a hint for your own further experiments involving different PN53x controllers and/or different readers bearing these chips. Good luck!

Kind regards,
Tomas Rosa

Last edited by tom314 (2010-07-15 07:55:36)

Re: Passive target mode initialization *without* secondary reader

This is awesome!

I've tried to do this myself, but I didn't got it to work that quickly, when then I was intrigued by other problems I never looked back into it. Great job Tomas! I'll let you know if it works the same with other (PN53x) devices as soon as I find some time to test it.

Keep up the good work!

Cheers, roel

Re: Passive target mode initialization *without* secondary reader

Tom, are you actually able to get reliable emulation with a real reader?

Re: Passive target mode initialization *without* secondary reader

sargun wrote:

Tom, are you actually able to get reliable emulation with a real reader?

Hi, the code posted above worked “against” CardMan 5321, the emulator was SCM SCL3710 (cf. above).

I have verified the emulator device was able to communicate with the reader on the data link layer. This was the main aim - to enable passive target mode communication without using the secondary "starting" reader to perform fw-enforced anticollision procedure.

I cannot, however, guarantee that this code alone always leads to a reliable PICC emulator, since other key aspects must be encountered as well. Namely, there is the speed of the code driving the SCL3710 dongle, since using the USB connection with a PC/MAC, the response rate obtained is far outside standard-enforced timing (cf. ISO 14443A).

So, I cannot say this solves the whole emulation problem. I have solved just a part of it - I hope one of those important parts. Another task is to speed up the response rate. Perhaps, an embedded microcontroller shall be employed. Please see other topics on this subject in this forum.

One more note on the PICC emulation itself:
I would like to emphasize, that the one and only reason of not using the built-in anticollision procedure of PN53x (I am still talking about passive mode target) is that we sometimes need to set the UID to an arbitrary value.

This is definitely needed for several access control systems. This is, on the other hand, unnecessary for applications like electronic passports (at least for a majority of them), EMV contactless cards, etc. The reason is that these applications do not care about the particular UID value at all.

Therefore, when emulating e.g. e-passport, I would definitely suggest using just this embedded anticollision procedure of PN53x. Of course, the UID will be then limited to a format like 08 X Y Z, but who cares? This mask perfectly fits a random UID (in fact, it is regarded as a random UID) according to ISO 14443A which many e-passports do use anyway.

I have to admit I did not read the latest emulation code of libnfc, so I do not know if the built-anticollision procedure of PN53x is somehow supported. In the clunky old version 1.3.4 I have played with, this procedure was regarded only as an obstacle that had to be bypassed. I would like to stress that this is true only sometimes.

To study relay attacks on e-passports, EMV contactless cards, etc., this built-in anticollision procedure is far enough while cancelling out any timing problem (because PN53x internally can respond fast enough). Finally, I would definitely vote for adding support of this functionality into the passive mode target API – if it is not already there now. If it is there, I would vote for using it whenever possible :-)

Kind regards,
Tom

PS: Sorry for the late reply. My spam filter swallowed the notification about your post...

Last edited by tom314 (2011-03-07 09:07:58)