NOTE: This post was imported from my previous blog – v3l0c1r4pt0r.tk. It was originally published on 25th July 2017.
As I promised some time ago, now I am going to describe process of pre-personalization of a JCOP card. JCOP is one of the easier to get JavaCard-compatible cards. However they cost a bit. The problem with the ones available from eBay sellers is lack of pre-personalization. Ok, there are some advantages of buying not pre-personalizaed card, like ability to set most of its parameters, but by the way it is quite easy to make such card unusable.
Online resources, as I mentioned in the first part of the tutorial, are not very descriptive. They say that there is such thing like pre-personalization and it has to be done before using the card, flashing applets, using them and so on. There is only one source that helps a little bit. Someone has written script for the process. However there are two problem with the script. The first one is that it is written in some custom language and internet does not know about the interpreter, it is probably something provided by NXP – manufacturer of JCOP for its customers and neither me nor (probably) you, reader, are their customers. The consequence is that we can have script in custom language, with commands like ‘/select’ or ‘/send’. Fortunately, documentation of ISO 7816 (smart card connection), allows to decipher this. So this problem could be finally solved. Another problem is lack of command values and addresses in memory, so we do not know where and how to read/write/execute anything. After really deep search in Google, finally, I was able to find out all the missing values, so this tutorial could be written.
Process overview
Ok, after this way too long historical introduction, let’s see what will be needed. I assume, you are already able to communicate with your card using raw PDUs. If you don’t, up to this point there are quite a few resources to learn from, so I will not describe this. The most important thing here is to have so called transport key (KT). If you do not have it, go get it now. Seller should provide it to you, and if he did not, you are stuck, since the first step requires this key.
So, basically steps will be as follows:
- Select root applet with Transport Key
- Boot the card
- Read/write some data
- Protect the card
- Fuse it
Easy? Easy. But only if you know some hex numbers. Ok, here, one big WARNING: the last step is irreversible and can be done by mistake quite easily, so think twice before sending anything, and if you are sure, that you are done, think twice again, before issuing it.
Pre-personalization, step by step
At first, we use Transport Key to select proper applet. Format of SELECT command is as below:
CLA=00 INS=A4 P1=04 P2=00 Lc=10 (...)
Where CLA is always zero, INS means SELECT, P1, according to ISO7816 means selection by DF name and Lc is length of KT. After that, key have to be appended. Of course, whole APDU is to be given to communications program as binary values or hex values only.
What now follows is specific to NXP cards only and is mostly undocumented publicly. First of such commands is BOOT command. Its format is as follows:
CLA=00 INS=F0 P1=00 P2=00
Now double care have to taken, because FUSE command should be available after this point and its APDU consists only of zeros, so every mistake might make the card unusable, since security keys are generated randomly for each card.
Reading memory
Now the most important values to read are called CM_KEY and GPIN in memory dump, I shared in the previous post on the topic. First one starts at offsets: 0xc00305, 0xc00321 and 0xc0033d and are 0x10 bytes long. The other one can be found at offset 0xc00412 and by default should be 5 bytes long. However maximum length is also 0x10, so it is better to make sure the length is really 5 by reading byte at offset 0xc00407. To sum up following commands need to be issued and results be saved for future use:
CLA=C0 INS=B0 P1=03 P2=05 Lc=10 C0 B0 03 21 10 C0 B0 03 3D 10 C0 B0 04 07 01 C0 B0 04 12 xx
Where CLA + P1 + P2 is concatenated address of memory area to read, INS=B0 is read command and Lc contains length of data to read.
Writing data
Alternatively, it is possible to write custom values to these buffers. This is especially encouraged for users who want to use the card not only for testing. Overwriting the values could be done with following:
CLA=C0 INS=D6 P1=03 P2=05 Lc=10 (...) C0 D6 03 21 10 (...) C0 D6 03 3D 10 (...) C0 D6 04 12 05 (...)
Where user data is filled with some random data of length in Lc field.
Required values
Beside securing keys, it is required to set CM_LIFECYCLE value to 0x01 and make sure all fields related to keys and PIN have proper values. Here, my memory dump can be used as reference, since I initialized the card before dumping the memory.
Finishing
After setting all the fields to desired values, there are two more steps to do. First one is issuing PROTECT command. It looks as below:
CLA=00 INS=10 P1=00 P2=00
And finally, sending FUSE command with:
CLA=00 INS=00 P1=00 P2=00
Here again, remember, that this command cannot be undone!
Well done! Your card should now be pre-personalized and ready to use, even in production environment. At the end, one remark: probably FUSE command does not need to be issued at all. However, if it is not issued, the card is completely insecure and should not be used in production.
Previous part of this tutorial can found under this link.
This is a great resource and the related memory map you built are also really good.
It’s important to note that the memory map / config parameter offsets do vary across the various releases of the cards. The same address won’t be good for many parameters between a J2A080 and a J3D081, for example.
One enhancement to your work might be describing the process which you would undertake to adapt what you know of one card’s memory structure to another card anticipated to be from the same larger family.