10 Dec 2010

How to access to MIFARE memory

To be able to read/write to/from MIFARE memory there is javacardx.external package specified in JavaCard 2.2.2 standard.
It specifies MemoryAccess interface and Memory class.
First we have to get object of MemoryAccess object like:

oMemAccess = Memory.getMemoryAccessInstance(Memory.MEMORY_TYPE_MIFARE
                                          , null
                                          , (short)0);

Memory.getMemoryAccessInstance() method has the following parameters:
  • memoryType - the desired external memory subsystem. Could be MEMORY_TYPE_MIFARE or MEMORY_TYPE_EXTENDED_STORE.
  • memorySize - the array containing the desired size in bytes, if applicable, in the external memory subsystem. This parameter is ignored for MIFARE memory type.
  • memorySizeOffset - the offset within the memorySize array where the 32 bit memory size number in bytes is specified. This parameter is ignored.
As you can see from above parameters list we need only specify memory type to get access MIFARE memory.
Then to write data to we can use MemoryAccess.writeData() method like:

             dataToWrite                     // the source data byte array
           , (short) 0                       // the byte offset in data buffer
           , (short) dataToWrite.length      // the length of data
           , thisCardPwdArray                // the byte array containing the 
                                             // key (password)
           , (short)0                        // the byte offset into the key 
                                             // array where the key data begins
           , (short) thisCardPwdArray.length // the length in bytes of key
           , (short) (blocknum / 4)          // sector number
           , blocknum)                       // block number

I'd like to mention one point about sector and block numbers. There are 2 type of addressing mode:

  • Absolute mode where block number accepts values 0..63 and sector number will be ignored.
  • Relative mode where block number accepts values 0..4 and sector number must be correctly set according to MIFARE memory layout.
To read data there is the method MemoryAccess.readData():

               readBuf                         // destination buffer
             , (short) 0                       // offset in destination buffer
             , thisCardPwdArray                // key (password) array
             , (short)0                        // offset in key array
             , (short) thisCardPwdArray.length // key length
             , (short)secnum                   // sector number
             , (short)blocknum                 // block number
             , DATA_LEN)                       // number of bytes to read

All parameters have the same meaning as in writeData() method.

One additional remark: if the password to access MIFARE memory is incorrect there is no retry mechanism. You have to start from the beginning. The reason why it has implemented like that is absence of key counter like in PIN key.

3 Dec 2010

Usage of dynamic/diversified data during applet installation

In this post I'd like to talk a little about usage of dynamic/diversified data in install() method of JavaCard applet.

But first let me explain what is dynamic/diversified data is. It is pretty simple. If you are reading some file during applet installation and this file content is different from one card to another you are using dynamic data. As an example of such kind of data could be ICCID or IMSI of the card. The diversified data is the kind of data in the file where you have some master key and for each card you have some generation mechanism which will guarantee uniqueness of each card.

Okay, I do hope it is clear what is dynamic/diversified data is. Now back to the subject of this post. The main message of it is:

 Do not use any dynamic/diversified data during your applet installation! 

Now let me explain why. Most of the (if not all) SmartCard manufacturers are not using regular APDU commands to personalize each card as it is time consuming. Just imagine how much time it will take to produce card by creation of each file with CREATE FILE APDU and then to update its content by UPDATE BINARY/UPDATE RECORD APDU commands if your speed limited with PPS. As each command involves SmartCard Operating System to treat it, to verify all security conditions, to perform required operation. When you have to produce millions of cards per day it is unacceptable. This is why the card production process was splitted to 2 stages:
  • Master card creation 
  • Daughter card creation 
What each stage means.
Master card was created only once for each type of the SmartCard profile and for its creation regular APDU commands were used. Afterwards by special mechanism all dynamic parts which are specific for each card were determined and separated from static part and card memory dumped.

Then for daughter card creation (these is actually cards which will be produced in larges amount) this memory dump is used i.e. instead of sending each APDU command one by one and pushing OS to treat them, production writes directly to card memory. And then the small part which is unique for the each card will be  personalized by regular APDU. That is much faster.

And if you use dynamic data during applet installation it will force your applet installation command to move to dynamic part which is slowing down production process. Moreover it is quite difficult to recognize if your applet is really using dynamic data. If it is just reads it to store inside the applet, the automatic mechanism of detection may not trigger, because memory will be the same. It means if by automatic mechanism your applet is considered as static, your applet will get incorrect data as static part is located before dynamic part.

So, what is the solution if you really need to use dynamic data? Implement it other way round:
  • Post process personalization of the applet by special commands 
  • Get necessary information in runtime 
  • etc. 
Which way is right depends on your applet design and functionality.